Skip to content

docs(r3): post-merge fix-forward — PB-4 §16 + PB-3 §9 Step 2 contradictions - #3138

Merged
briansrls merged 42 commits into
mainfrom
docs/director-l25-postmerge-cleanups
May 15, 2026
Merged

briansrls merged 42 commits into
mainfrom
docs/director-l25-postmerge-cleanups

Conversation

@briansrls

@briansrls briansrls commented May 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Post-merge fix-forward addressing residual issues from merged PR #3077 / #3085 / #3126 at 2026-05-15T00:21Z. Now covers 4 post-merge findings across 2 docs (PB-4 lower + PB-3 parse L2.5s).

Issues addressed

PB-4 lower §16 (per cursor APPROVE_WITH_COMMENTS PR #3077)

§16 "Memory disciplines applied" bullet said "diagnostics coupled INTO PreInferDag via biconditional" — but §4.3 (per openai-pro DiagnosticAnchor fix b812db9) constrains biconditional to PortAnchor-only. Other anchor kinds (DeclarationAnchor / RecordFieldAnchor / SurfaceFormAnchor) couple without port-state coupling.

Fix in commit f08b952: §16 bullet honors §4.3 anchor-typed framing.

PB-3 parse §9 Step 2 (per claude APPROVE PR #3126 exploratory obs)

§9 Step 2 row described diagnostics as "coupled INTO SurfaceModule" as if live — §4.3 correctly marks it PROPOSED. Same feedback_discipline_change_audit_all_contract_mentions pattern.

Fix in commit f08b952: §9 Step 2 row clarified — "PROPOSED extension per §4.3".

PB-3 parse §3.2 GrammarSpec parallel-authority (per codex REQUEST_CHANGES PR #3126)

§3.2 says GrammarSpec is compile-time-only NOT runtime-interpreted (per Decision 3.B (b)). But proposed stage contract still took grammar: GrammarSpec as runtime input. Two authorities (compiled tables + runtime spec value). P2 violation.

Fix in commit cfe842b: §4.3 signature fn parse(tokens) -> Result<SurfaceModule, ParseDiagnostic> — NO runtime GrammarSpec input.

PB-3 parse §4.3 fail-closed weakening (per codex REQUEST_CHANGES PR #3126)

Live parser at parse_generated.rs:138 returns Result<SurfaceModule, Diagnostic> (fail-closed). Earlier doc proposed embedded-diagnostics-in-SurfaceModule shape — would let partial-parse states be constructible. P3 + Practices 1/2 violation.

Fix in commit cfe842b: signature preserves Result-sum. Cross-stage discriminator named: Result-sum (parse + emit) for fail-fast output domain; typed-state-with-coupled-diagnostics (lower + infer) for structural-output-with-partial-failure domain.

Pattern

All 4 findings cluster around feedback_discipline_change_audit_all_contract_mentions — when substantive review-cycle fixes change a discipline framing in one section, audit ALL sections (framing + contract + handoff + cross-references) before merge. This session has surfaced this pattern 5+ times now.

Test plan

  • Reviewer-cycle on this fix-forward PR (2 distinct provider approvals + CI green)
  • Admin-merge per standing authorization

🤖 Generated with Claude Code

briansrls and others added 11 commits May 14, 2026 18:27
…ratification

Director-tier L2.5 model for PB-2 tokenize per operator 2026-05-14
ratification (Decision 1.A scoping = Option A).

PB-2 is the FURTHEST-ALONG pipeline stage — substrate authority
already lives in `.dag`:
- src/v3/std/tokenize.dag (Token + TokenKind taxonomy; LIVE 143
  lines)
- src/v3/compiler/tokenize.dag (tokenizer implementation; LIVE
  154 lines)
- src/v3/compiler/src/tokenize_generated.rs (AUTO-GENERATED; 362
  lines)

This is the END STATE that all other pipeline-stage migrations
target. PB-2 L2.5 is correspondingly lighter — mostly verification
+ residual hand-Rust retirement, NOT new substrate authoring.

Distinct §9 4-step framing:
- Step 3 = VERIFY substrate completeness (audit per
  feedback_paper_shrink_variants)
- Step 4 = HANDOFF/RETIRE residual hand-Rust scaffolding
  (coordinates with PB-Bootstrap-Process lane for codegen-driver
  retirement)

Captures audit dimensions explicitly:
- scanner-class definitions = declarative byte-pattern membership
- recognition tables = closed-axis enums
- state machine = structural transitions
- no V2 `pub mod tokenize` absorption check

§12 Q1: codegen-driver retirement scope — Director-recommend
PB-Bootstrap-Process handles all codegen-driver retirement
cross-cuttingly (not per-stage paper-shrink risk).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-pure-bootstrap-zero.md

Per cursor PR #3085 finding: §12.6 explicitly tables only 4
pipeline-stage migrations (emit→lower→infer→parse); tokenize is
per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085
commit 89fbd7a applied here.

INVARIANTS P1 — documentation must not overstate authority cites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-2 live state honesty

Same class as codex INLINE BLOCKING #3126 finding 1 (live state
honesty for diagnostic coupling) applied preemptively to PB-2
tokenize L2.5.

PB-2 §4.3 had "diagnostics coupled INTO List<Token>" framing
which would overstate the live carrier shape (bare List<Token>
has no diagnostic field; tokenize_generated.rs:96 today returns
Result<Vec<Token>, Diagnostic>).

Fix: §4.3 reframed with PROPOSED substrate extension explicit —
new `TokenizedSource { tokens, diagnostics }` wrapper carrier as
the typed-state output. Step 2 brief includes wrapper authoring
in pipeline-slot PR scope.

Same discipline as PR #3126 commit bdff8c5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…trap.md not -zero.md)

Per cursor APPROVE_WITH_COMMENTS /api/reviews/12087: PB-2 lane is
defined in docs/design-pure-bootstrap.md §"PB-2 — tokenize retire"
(line ~134), NOT docs/design-pure-bootstrap-zero.md. The -zero.md
doc has Subsumed-lanes list with PB-1/PB-4/PB-5/PB-6 but NOT PB-2.

Propagated fix applies same cite-error correction as PR #3066 §1.8
discipline: cite the actual doc, not an adjacent doc with similar
name. INVARIANTS P2 single-authority-citation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cursor APPROVE_WITH_COMMENTS (/api/reviews/12093) caught two
substantive contradictions I introduced when adding TokenizedSource
in commit 2b9756b:

1. §4.3 vs §9 Step 2 signature mismatch — §4.3 said `-> TokenizedSource`
   but §9 Step 2 row still said `-> List<Token>`. Same
   `feedback_discipline_change_audit_all_contract_mentions` issue
   that's recurred 4x this session.

2. §4.3 referenced "§12 Q-new" but §12 only had Q1-Q5; broken anchor.

Fix:
1. §9 Step 2 row updated: signature `-> TokenizedSource` with
   wrapper carrier shape `{ tokens, diagnostics }` per §4.3
2. §4.3 anchor updated: "§12 Q6" (resolved)
3. Added §12 Q6: TokenizedSource carrier shape ratification —
   (a) wrapper record vs (b) per-Token diagnostic coupling;
   Director-recommend (a) for PB-3 SurfaceModule parallelism
4. §14 + §15 + §16 Q-list refs updated to Q1-Q6

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codex REQUEST_CHANGES (sha b881de2) with 2 substantive findings:

1. §4.1 Token shape claim "optional lexeme: String" — wrong per
   live substrate at src/v3/std/tokenize.dag:65-67. Live Token
   has 2 fields only (kind + span); lexeme-content lives ON the
   TokenKind variants (Ident(String) / IntLit(String) / etc.).

   Fix: corrected §4.1 to reflect live carrier shape; payloads
   on TokenKind variants noted explicitly.

2. §12 Q4 substrate-completeness audit scoped only to
   tokenize_generated.rs — missed the regen_tokenize codegen-
   driver boundary. If regen_tokenize carries scanner-logic
   decisions (rather than mechanical template-rendering of
   substrate facts), the substrate isn't complete — the driver
   IS hand-Rust scanner logic in disguise.

   Fix: Q4 audit extended with (d) regen_tokenize codegen-
   driver logic audit + (e) ROADMAP.md deferral row option per
   feedback_paper_shrink_variants P5 receipt discipline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… scaffold disclosure

Codex REQUEST_CHANGES (sha b881de2, full body) caught 2 substantive
overstatements:

1. §2 line 46 claimed "tokenize failures produce typed
   TokenizeDiagnostic variants" — but live tokenize_generated.rs:96
   returns generic `Result<Vec<Token>, Diagnostic>` with
   `Diagnostic::TokenizerError { message, span, correction }`. Typed
   TokenizeDiagnostic is a PROPOSED extension, not live state.

   Fix: §2 reframed with live state explicit + TokenizeDiagnostic
   marked PROPOSED per PR #3077 §12 Q7 ratification path.

2. §1 line 22 + §6 + §9 Step 2 line 198 framed PB-2 as "mostly
   verification" — but live tokenize.dag:16-30+ has TWO explicit
   tracked scaffold zones:
   - SG-1a: regen_tokenize parses raw source text for
     dag_keyword_set / dag_operators (ValueBody::Unparsed)
   - Character-level under-consumption: StringEscapeSpec /
     LocalPunctSpec.pattern / string_literal_delimiter as opaque
     Strings; hidden Rust character predicates (byte.is_ascii_digit
     etc.) at tokenize_generated.rs:15-22 leaking through codegen

   Residual hand-Rust is NOT just the codegen artifact — it includes
   (a) regen_tokenize logic, (b) SG-1a raw-text-extractor scaffold,
   (c) character-predicate scaffold leaking through codegen.

   Fix: §1 + §6 + §9 Step 2 reframed honestly. PB-2 is "FURTHER
   ALONG but not complete"; Step 4 carries scaffold-retirement
   scope, not just codegen-artifact retirement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tions

Two post-merge doc-internal contradictions caught by reviewers
after operator merged PR #3077 / #3126 / #3085 at 2026-05-15T00:21Z.

**PR #3077 PB-4 lower §16 fix**:
§16 "Memory disciplines applied" bullet said "diagnostics coupled
INTO PreInferDag via biconditional" — but §4.3 (per openai-pro
DiagnosticAnchor fix commit b812db9) constrains biconditional
to PortAnchor-only. Other anchor kinds (DeclarationAnchor /
RecordFieldAnchor / SurfaceFormAnchor) couple without port-state.
Fix: §16 bullet honors §4.3 anchor-typed framing.

**PR #3126 PB-3 parse §9 Step 2 fix**:
§9 Step 2 row described diagnostics as "coupled INTO SurfaceModule"
as if live — §4.3 correctly marks it PROPOSED. Same
feedback_discipline_change_audit_all_contract_mentions pattern
that's recurred this session.
Fix: §9 Step 2 row clarified — "PROPOSED extension per §4.3";
Step 2 PR scope includes authoring the diagnostics field
extension, NOT a live coupling.

Per feedback_discipline_change_audit_all_contract_mentions: when
a substantive fix changes a discipline framing, audit ALL sections
(framing + contract + handoff). Post-merge audit surfaced these
residual contradictions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ec parallel-authority + fail-closed weakening)

Codex REQUEST_CHANGES on already-merged PR #3126 (/api/reviews/12175):
2 substantive findings on the post-merge doc.

**Finding 1 (P2 violation — GrammarSpec parallel authority)**:

§3.2 says GrammarSpec is compile-time-only, NOT runtime-
interpreted (per Decision 3.B (b) operator override). But the
proposed stage contract still took `grammar: GrammarSpec` as
runtime input. Creates two authorities (compiled parser tables
+ runtime GrammarSpec value).

Fix: §4.3 signature reframed to `fn parse(tokens: List<Token>)
-> Result<SurfaceModule, ParseDiagnostic>` — NO runtime
GrammarSpec input. Compile-time generated parser tables consumed
via internal dispatch. Step 2 + Step 4 rows updated.

**Finding 2 (P3 + Practices 1/2 — fail-closed weakening)**:

Live parser at parse_generated.rs:138 returns `Result<SurfaceModule,
Diagnostic>` (fail-closed; aborts on first error). Earlier draft
proposed `SurfaceModule` with embedded diagnostics — would let
partial-parse states be constructible + let downstream observe
"success" output after parse failure. Violation of fail-closed
discipline.

Fix: signature preserves Result-sum (matches live + emit's
pattern). Distinguished cross-stage:
- Result-sum (parse + emit): fail-fast output domain
- Typed-state-with-coupled-diagnostics (lower + infer): structural
  output domain where partial-failure IS valid intermediate

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…16 fail-closed honesty

Cursor caught 2 more post-merge contradictions on PR #3126:

1. §4.1 line 81 "construction-time invariant" talks about
   "ParseDiagnostic in the diagnostic stream" tied to SurfaceModule
   path — but §5.2 + live parse_generated.rs:138 use
   Result<SurfaceModule, Diagnostic>. §4.1 reads as claim about
   today's plumbing.

   Fix: §4.1 reframed — live boundary explicit (Result-sum);
   construction-time invariant scoped to Ok-arm SurfaceModule +
   Err-arm ParseDiagnostic, no partial-parse with embedded
   diagnostics.

2. §16 line 397 cites C-8 as "ParseDiagnostic coupled INTO
   SurfaceModule" without qualifier — but §4.3 (post codex
   REQUEST_CHANGES fix) constrains to Result-sum.

   Fix: §16 bullet honors §4.3 Result-sum framing; cross-stage
   discriminator named.

Same recurring feedback_discipline_change_audit_all_contract_mentions
pattern — substantive fix to §4.3 + §9 Step 2 left §4.1 + §16
inconsistent. Post-merge audit catches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review metadata

  • Provider / model: codex / unknown
  • Commit: f08b9525 · Trigger: schedule
  • Thinking: 216s wall

BLOCKING (2)

Root Cause

  • docs/design-tokenize-stage-l25-model.md diagnostic carrier draft copied the generated Rust scanner enum name instead of binding to the live .dag character-class authority → use CharClass/a declared substrate ref and cite the owning .dag declaration.
  • docs/design-tokenize-stage-l25-model.md TokenizedSource was introduced locally but not reconciled with the pipeline boundary/parse input contract → specify whether parse consumes TokenizedSource.tokens while diagnostics remain on a retained stage carrier, or change the downstream signature/carrier flow explicitly.

⚠️ Two substrate-boundary contradictions should be fixed before this design doc becomes worker-brief authority.

Comment thread docs/design-tokenize-stage-l25-model.md Outdated
```
// Typed reference carriers (cross-stage discipline per openai-pro
// PR #3077 BLOCKING + INVARIANTS P2/P3):
type ScannerClassRef = ScannerCharClass // closed-axis sum from tokenize.dag

This comment was marked as resolved.

Comment thread docs/design-tokenize-stage-l25-model.md Outdated

### §7.3 Sibling-stage coordination

Cross-stage discipline: **tokenize** → List<Token> → parse → SurfaceModule → lower → PreInferDag → infer → InferredDag → emit → EmissionResult.

This comment was marked as resolved.

briansrls and others added 2 commits May 15, 2026 01:03
…stop-signal

Cursor INLINE BLOCKING caught §3.2 line 66 "rules extend
automatically" weakens substrate-extension stop-signal. Thesis
discipline: a 7th TypeConnective variant requires explicit C1
audit + named infer-rule receipt.

Fix: §3.2 reframed. New TypeConnective variants do NOT extend
automatically; require explicit C1 substrate-extension audit +
named infer-rule receipt for the new variant's structural
inference behavior.

Per-variant structural facts means new variants need new
per-variant facts, NOT silent inheritance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…stic Practice 4 classification

Cursor INLINE BLOCKING /api/reviews/12218 (line:112): proposed
substrate coproducts (AlgebraAxis + InferDiagnostic) lack
🟢/🟡/🔴 classification + ledger/trigger per modeling-discipline
Practice 4 (Coproduct dissolution).

Fix: added 🟡 SCAFFOLD classification + named dissolution
trigger for both:

AlgebraAxis 🟡 SCAFFOLD:
- Trigger: Step 2 brief enumerates full algebra-axiom set
  against infer.rs check sites + verifies coverage parity
  with live verification.dag:146 AlgebraicLawKind 3-variant
  subset → promote to 🟢 TERMINAL.

InferDiagnostic 🟡 SCAFFOLD:
- Trigger: Step 2 brief enumerates full variant set against
  parse_generated.rs / lower.rs / infer.rs diagnostic emission
  sites → promote to 🟢 TERMINAL.
- Anti-bridge per Q6.5: does NOT collapse into
  CompilerDiagnosticKind without substrate-extension
  ratification per PR #3077 §12 Q7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls and others added 2 commits May 15, 2026 01:08
…on correction

Cursor INLINE BLOCKING /api/reviews/12251 line:130: §5.1 said
"every SurfaceItem variant maps 1:1 to a Declaration placeholder"
but live lower.rs:2950-2958 explicitly skips Let/Module/Import
in collect_symbols.

Verified via Read of lower.rs:2956-2958:
  SurfaceItem::Let { .. } => continue,
  SurfaceItem::Module { .. } => continue,
  SurfaceItem::Import { .. } => continue,

Fix: §5.1 reframed — DeclarationAllocating variants (Fn /
FnExternalBody / Data / TypeAtom / TypeRecord) map to
placeholders; NonDeclarationAllocating variants (Let / Module /
Import) skip allocation per live lower.rs behavior.

Let-bodies lower to Bind expressions in Pass 2; Module/Import
are parsed-facts preserved but un-declared.

Earlier "every SurfaceItem variant" framing overstated; would
have steered Step 2/3 worker into wrong allocation contract.
Per INVARIANTS P1/P2 live-state honesty + facts-flow-forward.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…adened

Cursor INLINE BLOCKING line:33: ElaborationSpec was defined only
as Surface→Behavior recipe mapping, but lower constructs
Declarations / TypeConnectives / BranchPatterns / Bindings as
well. Non-Behavior lowering decisions outside declared authority
violates THESIS substrate ownership + INVARIANTS P2.

Fix: §3.2 ElaborationSpec scope broadened to ALL lowering
decisions:

1. SurfaceItem → Declaration recipes (Fn / Data / Type variants +
   Let/Module/Import skip-allocation per §5.1)
2. SurfaceType → TypeConnective recipes (Atom / Arrow / Compose /
   Disj construction)
3. SurfaceExpr → Behavior recipes (Value / Transform / Branch /
   Loop / Bind construction)
4. SurfacePattern → BranchPattern recipes (ResolvedVariant /
   UnresolvedVariant / record-pattern construction)
5. Binding-site rules (Bind params + result_port construction)

ElaborationSpec is single-authority across ALL axes; no axis
lives in implementation-tier hand-Rust.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls and others added 10 commits May 15, 2026 01:10
…dependence clarification

Cursor APPROVE_WITH_COMMENTS /api/reviews/12265 line 197: §7.1
mixed two claims:
- "parse migrates AFTER tokenize substrate-side stable" (ordering)
- "PB-3 parse migration is independent of PB-2 tokenize migration
  status" (independence)

Read as contradictory by reviewers. Need one coherent story.

Fix: §7.1 reframed with two distinct axes explicit:

1. Substrate-stability ordering (SELF_HOSTING.md §2 bottom-up):
   tokenize Token carrier shape must be stable BEFORE parse
   migrates. Already true at HEAD (tokenize.dag:65-67 declares
   live carrier). ✓

2. Migration-timing independence (parallel-dispatch axis): PB-3
   parse migration ships in parallel with PB-2 residual-retirement
   work (SG-1a + character-level scaffold + codegen-driver
   retirement per PB-2 L2.5 §1). What parse needs is the stable
   Token CARRIER; PB-2's migration is about retiring residual
   hand-Rust, not changing the carrier.

Both claims coherent on the axis split; not contradictory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…n structural requirement

Cursor INLINE BLOCKING /api/reviews/12277 line:65: ParseDiagnostic
variants like UnexpectedToken lacked SourceSpan field;
List<ParseDiagnostic> cannot satisfy fail-closed source
attribution structurally without span on every variant.
INVARIANTS P2/P3 violation.

Fix: every ParseDiagnostic variant now carries SourceSpan
structurally:
- UnexpectedToken: added span: SourceSpan
- UnterminatedConstruct: opener_span: SourceSpan (already present)
- InvalidLiteral: added span: SourceSpan
- DuplicateRecordFieldLabel: added span: SourceSpan (current site)
  + prior_span: SourceSpan (prior site; both required)

Per INVARIANTS P2/P3 fail-closed source attribution discipline:
every diagnostic emission carries structural source-span
provenance; not optional.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tom-reference fix

Cursor INLINE BLOCKING /api/reviews/12279 line:29: §3.1 cited
`src/v3/compiler/src/tokenize.rs` as "current hand-Rust" for
Token carrier — but `tokenize.rs` (without _generated suffix)
doesn't exist. Live state has tokenize.dag (live substrate) +
tokenize_generated.rs (codegen artifact).

Per design-pure-bootstrap.md PB-2 lane: tokenize retire has
substantially landed. The reference was an earlier-draft
phantom from when Token-was-hand-Rust framing was the assumption.

Fix: §3.1 reframed — Token type lives in LIVE
src/v3/std/tokenize.dag:65-67 shared taxonomy; tokenizer
implementation also live at src/v3/compiler/tokenize.dag (154
lines); codegen artifact at tokenize_generated.rs. tokenize.rs
phantom reference removed explicitly. PB-2 substantially landed
per design-pure-bootstrap.md; residual scaffold-retirement
scope per PB-2 L2.5 PR #3127.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…et fix (compiler.dag → pipeline.dag)

Cursor INLINE BLOCKING /api/reviews/12281 line:138: §9 Step 2
referenced generic "compiler.dag" but dsl/gunbc/compiler.dag:24
explicitly directs internal pipeline (Tokenize → Parse → ...)
to src/v3/compiler/pipeline.dag, NOT generic compiler.dag.

Worker briefs authored against this doc would target the wrong
file for pipeline-slot declaration. P2 single-authority violation.

Fix: §9 Step 2 row in ALL 4 L2.5 docs (PB-2 / PB-3 / PB-4 / PB-5)
updated:
- "declared in compiler.dag" → "declared in src/v3/compiler/pipeline.dag (per dsl/gunbc/compiler.dag:24 — internal pipeline lives in pipeline.dag, NOT generic compiler.dag)"
- substrate column: "compiler.dag refinement" → "pipeline.dag refinement"
- §13 "Step 2 (pipeline-slot in compiler.dag)" → "pipeline-slot in src/v3/compiler/pipeline.dag"

Same phantom-citation class as the tokenize.rs phantom (commit
8ae37b4): I cited generic file path without verifying which
specific file is authoritative per project structure. Should
have grep'd dsl/gunbc/compiler.dag header notes before authoring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ipt unambiguity

Cursor INLINE BLOCKING /api/reviews/12283 line:181: Q5 said
Step 3b "full parser body .dag migration + parser body deletion
in same PR", but §15 sequence schedules Step 4 parity/deletion
AFTER Step 3b merges. P5 dissolution receipt ambiguous.

If Step 3b lands .dag parser body BEFORE Step 4 deletes Rust
parse() body, Rust + .dag parser bodies coexist temporarily —
paper-shrink-relocation risk per feedback_paper_shrink_variants.

Fix:
1. §9 Step 3b row reframed as "Step 3b/4 COMBINED" — atomic
   single PR (full .dag parser body + parity TestClaim +
   parse_generated.rs:138 deletion + census shrink). Cannot land
   .dag parser body before Rust deletion.
2. §12 Q5 phasing clarified:
   - Phase 3a (separate PR): grammar table extension; P5 receipt
     = ROADMAP deferral row naming Step 3b/4 as future-receipt
   - Phase 3b/4 COMBINED (single PR): atomic substrate substitution
3. §9 + §15 update notes: sequence collapses steps 12-17 into
   single dispatch+merge for combined phase

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codex high-level BLOCKING (sha 140eb6b) had 4 findings:
- Findings 3 + 4 already addressed in PR #3138 commits 0159773
  + a1607a8
- Findings 1 + 2 addressed in this commit

**Finding 1 (Diagnostic kind/record conflated)**:
§4.2 ParseDiagnostic was modeled as variants-directly with span
+ kind-fields mixed. Live Diagnostic at diagnostics.dag:150 uses
record-wraps-kind pattern (`{ kind, span, message, correction }`).
Need consistent shape.

Fix: refactored to record-wraps-kind:
- `type ParseDiagnostic { kind: ParseDiagnosticKind, span: SourceSpan }`
- `type ParseDiagnosticKind = UnexpectedToken | UnterminatedConstruct | InvalidLiteral | DuplicateRecordFieldLabel | ...`

Span lives on ParseDiagnostic record (single source of truth);
variant-specific spans (opener_span / prior_span) remain on kind
variants where meaningful.

**Finding 2 (PB-2 §6 obsolete sibling-lane assumption)**:
§6 line 198 said "PB-2 Tokenize | src/v3/std/tokenize.dag (NEW
per PB-2 L2.5)" — but tokenize.dag is ALREADY LIVE per
design-pure-bootstrap.md §"PB-2 — tokenize retire" (substantially
landed).

Fix: §6 prereq table row updated to reflect LIVE state. PB-2's
residual scope is scaffold-retirement (SG-1a + character-level +
codegen-driver per PB-2 L2.5 §1), not carrier authoring. PB-3
consumes the live Token carrier; carrier shape stable across
PB-2 residual-retirement timing.

Findings 3 + 4 already addressed:
- Finding 3 (pipeline.dag target): commit 0159773
- Finding 4 (Step 3b/4 atomic vs sequential): commit a1607a8

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…el metadata" removed

Cursor APPROVE_WITH_COMMENTS line:79: §4.1 said "SurfaceModule
(verified live) carries List<SurfaceItem> + module-level
metadata" — but live parse_surface.dag:29 has ONLY
`{ items: List<SurfaceItem> }`. No metadata fields.

Phantom addition violated INVARIANTS P1 live-state honesty.

Fix: §4.1 reframed to match live carrier exactly. Same
phantom-addition class as tokenize.rs phantom (commit 8ae37b4).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-variant + diagnostic-table PROPOSED

Codex high-level BLOCKING (sha bf4d315) — 2 substantive findings:

**Finding 1 (AtomPayload stale)**:
§2 + §5 cited infer.rs:10 top-comment "Atom(Identifier { name,
resolved })" — but live substrate.dag:87 has 5-variant
AtomPayload sum: Literal | UnresolvedIdentifier |
ResolvedByStructure | ResolvedByName | TypeParam.

infer.rs top-comment is STALE vs live substrate. My doc inherited
the drift.

Fix: §2 enumeration corrected to all 5 AtomPayload variants per
live substrate.dag:87.

**Finding 2 (diagnostic-table PROPOSED, not live)**:
§2 + §4.1 + §4.3 said "diagnostics.contains(port_id)
biconditional" as if live — but Dag at substrate.dag:525 has
ONLY { declarations, nodes, ports, clusters }. NO diagnostics
field. Diagnostic-table is PROPOSED substrate extension.

Fix: §2 fail-closed note flagged PROPOSED — Step 2 PR scope
includes `diagnostics: Map<PortId, Diagnostic>` field extension
to Dag, OR PB-Substrate prereq adds it before PB-5 dispatch.

Same recurring feedback_grep_carrier_field_before_coupling_claim
discipline (PR #3126 SurfaceModule analogous case); needed to
grep type Dag fields BEFORE claiming the diagnostics field
exists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…SED diagnostic-table marking

Cursor INLINE BLOCKING line:94: §4.1 + §4.3 said "diagnostics
coupled INTO InferredDag" without flagging the diagnostic-table
as a substrate extension. Live Dag at substrate.dag:525 has
{ declarations, nodes, ports, clusters } — NO diagnostics field.
Earlier commit c0d96af added PROPOSED marking only in §2;
§4.1 + §4.3 needed same treatment.

Fix: §4.1 + §4.3 reframed with explicit PROPOSED substrate-
extension marking + reference to §2 for extension scope.
Construction-time invariant + structural coupling are both
contingent on the substrate-extension landing (Step 2 PR scope
or PB-Substrate prereq).

Same recurring feedback_grep_carrier_field_before_coupling_claim
discipline applied to §4.1 + §4.3 consistently with §2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls and others added 4 commits May 15, 2026 01:39
…ng resolved by PR #3077 merge

Cursor inline BLOCKING at docs/design-parse-stage-l25-model.md:119 (sha at
merge time of PR #3126) flagged a real internal contradiction:
- §6 (lines 191, 207, 308) claimed "Step 2 (pipeline-slot declaration) is
  unblocked"
- §7.2 (line 227) claimed "PR #3077 §12 Q7 must ratify before any Step 2
  worker brief authoring"

A worker reading the doc could land Step 2 (pipeline boundary) before the
diagnostic carrier's P2/P3 failure shape was fixed.

Resolution: PR #3077 (PB-4 lower L2.5) merged at 2026-05-15T00:21:19Z,
carrying the §12 Q7 ratification of the Decision 2.B per-stage diagnostic
extension path. The gate IS now satisfied at HEAD, so the resolution is
fact-update (annotate Q7 as DONE with the merge timestamp) rather than
retracting either §6 or §7.2.

Edits:
- §15 step 4: annotated "DONE 2026-05-15T00:21:19Z when PR #3077 merged"
  and added the explicit "Step 2 is now genuinely unblocked, not just
  procedurally next" framing so workers reading the sequence don't bypass
  the gate.
- §7.2 line 227: rewritten from "Q7 must ratify before Step 2 brief
  authoring" (future tense, the contradiction surface) to "Gate satisfied
  2026-05-15T00:21:19Z when PR #3077 merged; Step 2 worker brief authoring
  is unblocked at HEAD per §15 step 4." Cites the cursor finding as the
  resolution path.

§6 unblocking statements stay as-is — they were correct at HEAD; the
contradiction lived in §7.2's pre-merge framing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tep 2 unblocking claim

Codex BLOCKING finding 2 (sha 16d21f4, 216s thinking): the Q7 dependency
was recorded in §7.2/§15 but not in the other Step-2-unblocking sites at
§6 lines 191, 207, 308 — risking a worker reading "Step 2 unblocked" without
also reading the Q7 prerequisite.

Codex framing: "make Q7 a hard precondition wherever Step 2 is called
unblocked, or split Step 2 into pre-Q7 and post-Q7 scopes with separate
receipts."

Chose the first option since PR #3077 has already merged (2026-05-15T00:21:19Z)
and splitting into pre/post-Q7 scopes is no longer load-bearing. Annotated
all three §6 sites:
- Line 191 (Implication for PB-3 migration): cites gate + merge timestamp
  + explicit "must NOT be brief-authored before that merge timestamp."
- Line 207 (Critical observation): cites the Step 2 gate as PR #3077 §12 Q7
  + merge timestamp + P3 failure-shape consequence if violated.
- Line 308 (Director-recommend phase list): cites gate + §7.2/§15 step 4
  cross-refs + merge timestamp.

Codex BLOCKING finding 1 (GrammarSpec carrier non-existence) verified
already resolved at HEAD via commit c97dc15 — every GrammarSpec mention
now explicitly marks it as a concept-not-carrier; Step 2 signature is
`fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>`
with no GrammarSpec parameter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…icity + Q1 ratification-pending status

openai-pro REQUEST_CHANGES on PR #3126 sha 16d21f4 flagged three findings.
Findings 1 + 2 (signature vs realization mismatch under LAYER MODEL + P2/P3
boundary discipline) were already resolved at HEAD by earlier fix-forward
commits — Step 2 signature is now `fn parse(tokens: List<Token>) ->
Result<SurfaceModule, ParseDiagnostic>` matching live `parse_generated.rs:138`
with no GrammarSpec parameter and no diagnostics-coupled SurfaceModule
extension (§4.3 Result-sum disposition).

Finding 6 (TRACKED vs UNTRACKED DEBT — Step 3b/4 same-PR vs two-PR):
§9 had both a "Step 3b/4 COMBINED" row (line 250) and a leftover separate
"Step 4: Parity test" row (line 251) — internally contradictory. §15 also
still sequenced Steps 3b + 4 as four separate authoring/dispatch/ratify
beats (steps 12-17), contradicting §12 Q5's "same PR" decision and the
explicit "Update to §15" note at §12 line 325.

Resolution: collapsed §9 to one COMBINED row absorbing the parity-TestClaim
mechanics + P5 dissolution receipt from the deleted Step 4 row; collapsed
§15 steps 12-17 into single COMBINED authoring + dispatch + ratify (steps
12-14). Added explicit `feedback_paper_shrink_variants` reasoning in both
sections.

Finding 2.5 (PM intent — substrate-capability bundled vs separate):
§12 Q1 line 288 said "Director-recommend: (b) bundled" while §13 line 340
listed substrate-capability as a non-goal of PB-3 and §15 step 11 had
"WAIT for substrate-capability landing" — three sections, two different
execution paths.

Resolution: annotated Q1 as "PENDING operator/PM ratification" with
explicit default-execution clause: until operator ratifies, the doc
treats substrate-capability as path (a) separate lane (matching §13 + §15
+ §9 row). If/when ratified to (b), §13 drops the non-goal and §15 step 11
collapses into the COMBINED Step 3b/4 brief.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… single enumerated authority

Codex caught me copying the prose summary at parse_tables.dag:23-29 (which
enumerates only SG-2c-numbered families) instead of grepping the live
`^type [A-Z]` declarations. Result: SoftKeywordIdentRow (line 334) was
missing from §3.2 / §5.1 / §6 / §12 because it lacks an SG-2c-N number
in the prose summary.

Per `feedback_parallel_representation_debt`: structural fix is to stop
hand-enumerating in the doc — cite parse_tables.dag itself as the single
enumerated authority and use `type`-declaration line-anchors for the
worked example, not a hand-maintained count.

Edits:
- §3.2 §"Live substrate authority": replaced the SG-2c-numbered bullet
  list with `type`-declaration line-anchor enumeration including
  SoftKeywordIdentRow at parse_tables.dag:334 + the supporting enum
  BinaryOpLevel at line 133. Added codex-finding callout explaining the
  miss + the discipline shift.
- §3 preamble line:33, §3.2 line:45 callout, §3.2 line:57 framing,
  §3.2 §"Substrate authority" line:71, §5.1 line:171-180, §12 Q2 line:298,
  §12 Q6 line:334: all hardcoded "6 table-families" counts dropped; doc
  now points readers to §3.2 enumeration / `parse_tables.dag` directly.
- §5.1 sub-enumeration list (the parallel 6-item list at lines 173-178)
  deleted; replaced with redirect to §3.2 + restated 3a-vs-3b/4 scope split.

Code-level check before commit: `grep -nE '^type [A-Z]' src/v3/compiler/parse_tables.dag`
returns 7 types: BinaryOpLevel (133), BinaryOpRow (167), TopLevelItemKwRow (289),
SoftKeywordIdentRow (334), BracketRow (385), PrimaryPrefixRow (449),
PrimaryAtomRow (486). Doc enumeration matches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 15, 2026
…ource + cite concrete P5 receipts

Codex review id 12370 on sha d15e1f2 raised two load-bearing planning-shape
findings. Both addressed; this commit ports the same edits already living on
fix-forward branch docs/director-l25-postmerge-cleanups (PR #3138 commit
6adb992) onto PR #3127's branch directly so codex BLOCKING resolves on
this PR's own HEAD rather than waiting on PR #3138 merge.

Finding 1 — parallel boundary carriers (INVARIANTS P2 / Practices 3+5):
§4.3 + §9 Step 2 + §12 Q6 named `TokenizedSource { tokens, diagnostics }`
as the output, while §2/§7.2/§7.3 named `List<Token>`. Same misclassification
removed from the parse L2.5 (PR #3138 §4.3): tokenize sits in the fail-fast
output domain alongside PB-3 parse + PB-6 emit (a partial token list with a
corrupt token in the middle is not a valid downstream input for parse), so
the failure couples via `Result`, not into the structural carrier.

Resolution:
- §4.3 rewritten to ratify `Result<List<Token>, TokenizeDiagnostic>` — the
  live `tokenize_generated.rs:96` shape — with no `TokenizedSource` extension.
- §9 Step 2 row signature updated to match; explicit "single canonical
  boundary carrier: List<Token> on the Ok branch" framing.
- §12 Q6 resolved REJECTED in-doc (no operator ratification needed;
  disposition follows from the cross-stage discriminator load-bearing in
  PR #3138 parse L2.5).
- §16 memory-disciplines bullets rewritten parallel to PR #3138 parse §16:
  Result-sum, no diagnostics field on `List<Token>`.
- §14 "Surfaces awaiting" trimmed Q6 from the operator-ratification list.

Finding 2 — soft deferral of `regen_tokenize` retirement (INVARIANTS P5):
deferral previously named "PB-Bootstrap-Process lane scope" without a
concrete ROADMAP.md row. Updated §9 Step 2 + Step 4 rows to cite the named
receipts:
- `docs/design-pure-bootstrap-zero.md:116` (PB-Bootstrap-Process lane:
  author bootstrap.dag + generated trampoline; sized M).
- `docs/design-pure-bootstrap-zero.md:118-123` (N=0 runtime verification
  gates).
- ROADMAP.md:467 (Character-level under-consumption in tokenize + syntax
  authorities — phase-2 char-class retype owns the codegen-driver path).
- ROADMAP.md:416 (Class 5 Gap 3 — top-level `ValueBody` boundary; gating
  substrate-capability for the phase-2 retype).
- ROADMAP.md:53 (T-PB-A — non-test census → 0 floor).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…stic to live CharClass authority

Codex Finding 1 (sha f08b952, 216s thinking): the §4.2 TokenizeDiagnostic
draft and the §5.1/§5.2 headings used `ScannerCharClass` / `ScannerClassRef`
— names that exist only as the *generated Rust enum spelling*, not as a
declared .dag substrate type. Verified via grep:

  grep -rn '^type CharClass\|^type ScannerC' dsl/ src/v3/

returns ONE authority: `dsl/std/unicode.dag:62`
  type CharClass = Whitespace | Digit | IdentStart | IdentContinue

consumed at `src/v3/compiler/tokenize.dag:103`
  data ascii_scan_order: List<CharClass> = [Whitespace, Digit, IdentStart, IdentContinue]

There is no `ScannerCharClass` declaration anywhere — that name was copied
from generated Rust without grep-verification, the same failure mode as
`feedback_grep_substrate_before_naming_ratification` (carrier-name
collision discipline).

Resolution:
- §4.2 TokenizeDiagnostic carrier: `expected_class: ScannerClassRef` →
  `expected_class: CharClass`, dropped the `type ScannerClassRef =
  ScannerCharClass` alias entirely; added a codex-finding callout citing
  the substrate authority + naming the failure mode.
- §5.1 heading "Byte → ScannerCharClass dispatch" → "Byte → CharClass
  dispatch"; bullets unchanged; added line-anchor cites for the substrate
  authority + explicit "NOT ScannerCharClass" disclaimer.
- §5.2 heading "ScannerCharClass → token-recognition state machine" →
  "CharClass → token-recognition state machine".

Finding 2 (TokenizedSource not reconciled with parse input contract): no
new fix required — already resolved by commit 6adb992 (TokenizedSource
extension dropped entirely; tokenize uses Result<List<Token>,
TokenizeDiagnostic>; List<Token> is the single canonical boundary carrier
consumed by parse). Codex was reviewing sha f08b952, which predated the
TokenizedSource drop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 15, 2026
…ive CharClass authority

Porting the same fix that landed on PR #3138 commit 367fdc2 onto PR #3127's
own branch so codex BLOCKING resolves on this PR's HEAD directly.

Codex Finding 1: §4.2 TokenizeDiagnostic + §5.1/§5.2 headings used
`ScannerCharClass` / `ScannerClassRef` — names that exist only in the
generated Rust enum spelling, not as a .dag substrate declaration. Live
authority is `dsl/std/unicode.dag:62` `type CharClass = Whitespace | Digit
| IdentStart | IdentContinue`, consumed at `src/v3/compiler/tokenize.dag:103`.

Resolution:
- §4.2: `expected_class: ScannerClassRef` → `expected_class: CharClass`;
  dropped the `type ScannerClassRef = ScannerCharClass` alias; added
  codex-finding callout citing the substrate authority.
- §5.1: heading + intro now cite `dsl/std/unicode.dag:62` directly.
- §5.2: heading "CharClass → token-recognition state machine".

Same failure-mode as `feedback_grep_substrate_before_naming_ratification`:
naming a substrate carrier without grep-verifying against live .dag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Status reply for the cursor INLINE BLOCKING at docs/design-tokenize-stage-l25-model.md:96 (review at sha f08b952). Same root-cause as the codex BLOCKING I addressed in commit 367fdc2 on this PR's HEAD. At current HEAD:

  • TokenizeDiagnostic.InvalidCharacter references expected_class: CharClass (the live .dag authority at dsl/std/unicode.dag:62), not the prior invented ScannerClassRef = ScannerCharClass alias.
  • The §4.2 block now cites the substrate authority explicitly: dsl/std/unicode.dag:62 declaration + src/v3/compiler/tokenize.dag:103 consumption (data ascii_scan_order: List<CharClass>).
  • §5.1 / §5.2 headings + intros also renamed; the codex-finding callout in the doc records the failure mode (carrier name copied from generated Rust enum without grep-verification — same family as feedback_grep_substrate_before_naming_ratification).

The same fix was also ported to PR #3127's branch (sha 9ae4ef6) since it carries the same tokenize doc.

— sent from zesty-bear-812

…in is Ok-branch propagation

Cursor INLINE at sha f08b952 worried that §7.3's cross-stage chain
"tokenize → List<Token> → parse → ..." was inconsistent with §4.3's
TokenizedSource carrier (diagnostics not flowing forward). At HEAD the
TokenizedSource extension is dropped (commit 6adb992); tokenize uses
Result<List<Token>, TokenizeDiagnostic>, so List<Token> IS the canonical
Ok-branch payload that flows forward and Err branches terminate the
pipeline fail-fast.

To make this explicit at §7.3 (instead of leaving readers to infer it
from §4.3), annotated the chain with:
- "Ok-branch propagation; Err branches are stage-terminal fail-fast per
  §4.3 Result-sum discriminator" framing prefix.
- Per-stage Result/typed-state annotations: tokenize/parse show
  Result<Ok, Err>; lower/infer show typed-state structural-output;
  emit shows Result<EmittedArtifact, EmissionDiagnostic>.
- Explicit "on any stage's Err branch the pipeline aborts at that stage
  (no partial-output propagation across boundaries)" trailer.

This makes the chain self-consistent vis-a-vis §4.3 without requiring
the reader to walk back-and-forth, and prevents future readers from
re-introducing a TokenizedSource-shaped extension to "make diagnostics
flow forward" — they already do, just via the Err branch terminating
the pipeline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 15, 2026
…anch annotation

Same edit as PR #3138 commit a8c0ff7 ported to this PR's branch. §7.3
cross-stage chain now annotates Ok-branch propagation + Err-branch
fail-fast termination explicitly, eliminating the apparent contradiction
between §4.3 (Result-sum) and §7.3 (List<Token> in the chain). They were
already consistent — Ok-branch payload flows forward; Err terminates —
but the annotation makes it self-evident at §7.3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…l scaffold dissolution trigger

openai-pro REQUEST_CHANGES on sha d15e1f2: §1 line:26 character-level
under-consumption scaffold named the problem but lacked a checkable
dissolution trigger. SG-1a scaffold above had the right shape — "once
those bodies lower structurally under compile_to_dag, delete the raw-text
extractor + derive directly from lowered Dag in same PR." Character-level
scaffold just said "PB-2 Step 4 carries this scope" — a lane assignment,
not a trigger.

Resolution: rewrote §1 item 2 with the same SG-1a-shape trigger structure:
- Substrate-consumption condition (a): scanner classes / string escape /
  local punctuation retype to `dsl/std/unicode.dag` `CharClass` /
  `char_in_class` (concrete field retypes named:
  `StringEscapeSpec.suffix: Char`, `LocalPunctSpec.pattern: List<Char>`,
  `string_literal_delimiter: Char`).
- Codegen-driver condition (b): `tokenize_generated.rs` no longer emits
  hidden `byte.is_ascii_*` predicates because the driver reads class
  facts structurally from lowered `tokenize.dag`.
- Same-PR dissolution: delete the parallel character-predicate scaffold
  in the same PR that flips substrate consumption — no Rust-and-`.dag`
  coexistence per `feedback_paper_shrink_variants`.
- Cross-ref to §9 Step 4 gating prereqs: ROADMAP.md:467 + ROADMAP.md:416
  Class 5 Gap 3 + std.unicode bootstrap/load-set decision (already cited
  in §9 from earlier commit 6adb992).

Per openai-pro's framing: "small fix — mirror the SG-1a scaffold wording
by naming the exact substrate-consumption condition and same-PR deletion
receipt for the hidden Rust character predicates."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 15, 2026
…l scaffold dissolution trigger

Same edit as PR #3138 commit 5a93d93 ported to this PR's branch.
§1 item 2 character-level under-consumption scaffold now carries the
same SG-1a-shape dissolution trigger structure: substrate-consumption
condition (a) + codegen-driver condition (b) + same-PR delete receipt,
with cross-refs to §9 Step 4 gating prereqs already cited.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Status reply for codex review id 12391 on sha cd6e8d15c — both findings already resolved at HEAD (commit a76f421 on this branch, three pushes ago). Current state:

  • Finding 1 (§4.3 ParseResult/SurfaceModule extension): §4.3 at HEAD (lines 136-148) opens with "Parse output is Result<SurfaceModule, ParseDiagnostic> — NO SurfaceModule diagnostics-extension" + an explicit codex-revision callout: "this section previously proposed an items + diagnostics extension to SurfaceModule modeled on PB-4 lower's PreInferDag / PB-5 infer's InferredDag. That model is REJECTED for parse." The corrected Result-sum framing now stands without contradiction.
  • Finding 2 (§16 bullet "typed-state SurfaceModule at output"): the bullet at HEAD (line 409) reads "feedback_state_space_vs_behavioral_invariants (parse output is Result<SurfaceModule, ParseDiagnostic> — the type rules out partial-parse states by construction; SurfaceModule itself carries no diagnostic field per §4.3)" — exactly the corrected framing.

Both fixes landed in commit a76f421 in response to codex's earlier review on sha cd6e8d1 (same review content, surfaced twice). Subsequent commits 0d79c8e (Q7 hard precondition at every Step 2 unblocking site), 46e3004 (openai-pro Step 3b/4 atomicity + Q1 ratification status), 3eeee0c (parse_tables.dag single enumerated authority including SoftKeywordIdentRow), 367fdc2 / a8c0ff7 / 5a93d93 (tokenize-doc CharClass binding + §7.3 chain annotation + character-level dissolution trigger) all on top.

PR HEAD is now 5a93d93. Dashboard please retally; cd6e8d15c is several pushes stale.

— sent from zesty-bear-812

briansrls and others added 2 commits May 14, 2026 21:59
…y-rejected sweep

Cursor review id 12405 (APPROVE_WITH_COMMENTS) caught the same
`feedback_discipline_change_audit_all_contract_mentions` failure mode
recurring: §12 Q6 was resolved REJECTED in commit 6adb992, and §14
"Surfaces awaiting" + §12 Q6 heading + §9 Step 2 row were updated, but
two §-internal contract restatements were missed:

- §14 acceptance criterion 11: "Operator/PM ratification on §12 Q1-Q6"
- §15 step 1: "Operator / PM-delegate ratifies §12 Q1-Q6"

Both contradicted §12 Q6 + §14 "Surfaces awaiting" (which already said
"Q1-Q5 only"). A worker reading §14/§15 could schedule sign-offs on Q6
after it was already resolved-rejected elsewhere.

Resolution: both sites now say "Q1–Q5" with the explicit Q6-rejected
crossref + "see §14/§15 for same scoping" pointer at the §14 criterion
so the three sections agree internally.

Cursor verdict was APPROVE_WITH_COMMENTS (substantive APPROVE — "fix the
checklist/sequence so every section agrees Q6 is closed"); the
exploratory volatile-line-anchor note is harmless and out-of-scope for
this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 15, 2026
…y-rejected sweep

Same edit as PR #3138 commit 887c696 ported to this PR's branch. §14
acceptance criterion 11 + §15 step 1 now say "Q1-Q5" with explicit
Q6-rejected crossrefs, aligning with §12 Q6 + §14 "Surfaces awaiting"
which already said "Q1-Q5 only".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 15, 2026
…ratification (#3127)

* docs(r3): PB-2 tokenize pipeline-stage L2.5 domain model — DRAFT for ratification

Director-tier L2.5 model for PB-2 tokenize per operator 2026-05-14
ratification (Decision 1.A scoping = Option A).

PB-2 is the FURTHEST-ALONG pipeline stage — substrate authority
already lives in `.dag`:
- src/v3/std/tokenize.dag (Token + TokenKind taxonomy; LIVE 143
  lines)
- src/v3/compiler/tokenize.dag (tokenizer implementation; LIVE
  154 lines)
- src/v3/compiler/src/tokenize_generated.rs (AUTO-GENERATED; 362
  lines)

This is the END STATE that all other pipeline-stage migrations
target. PB-2 L2.5 is correspondingly lighter — mostly verification
+ residual hand-Rust retirement, NOT new substrate authoring.

Distinct §9 4-step framing:
- Step 3 = VERIFY substrate completeness (audit per
  feedback_paper_shrink_variants)
- Step 4 = HANDOFF/RETIRE residual hand-Rust scaffolding
  (coordinates with PB-Bootstrap-Process lane for codegen-driver
  retirement)

Captures audit dimensions explicitly:
- scanner-class definitions = declarative byte-pattern membership
- recognition tables = closed-axis enums
- state machine = structural transitions
- no V2 `pub mod tokenize` absorption check

§12 Q1: codegen-driver retirement scope — Director-recommend
PB-Bootstrap-Process handles all codegen-driver retirement
cross-cuttingly (not per-stage paper-shrink risk).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): §12.6 citation fix — tokenize is PB-2 lane scope per design-pure-bootstrap-zero.md

Per cursor PR #3085 finding: §12.6 explicitly tables only 4
pipeline-stage migrations (emit→lower→infer→parse); tokenize is
per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085
commit 89fbd7a applied here.

INVARIANTS P1 — documentation must not overstate authority cites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): preemptive fix for PR #3126 codex BLOCKING propagation — PB-2 live state honesty

Same class as codex INLINE BLOCKING #3126 finding 1 (live state
honesty for diagnostic coupling) applied preemptively to PB-2
tokenize L2.5.

PB-2 §4.3 had "diagnostics coupled INTO List<Token>" framing
which would overstate the live carrier shape (bare List<Token>
has no diagnostic field; tokenize_generated.rs:96 today returns
Result<Vec<Token>, Diagnostic>).

Fix: §4.3 reframed with PROPOSED substrate extension explicit —
new `TokenizedSource { tokens, diagnostics }` wrapper carrier as
the typed-state output. Step 2 brief includes wrapper authoring
in pipeline-slot PR scope.

Same discipline as PR #3126 commit bdff8c5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3077 — fix PB-2 lane citation (design-pure-bootstrap.md not -zero.md)

Per cursor APPROVE_WITH_COMMENTS /api/reviews/12087: PB-2 lane is
defined in docs/design-pure-bootstrap.md §"PB-2 — tokenize retire"
(line ~134), NOT docs/design-pure-bootstrap-zero.md. The -zero.md
doc has Subsumed-lanes list with PB-1/PB-4/PB-5/PB-6 but NOT PB-2.

Propagated fix applies same cite-error correction as PR #3066 §1.8
discipline: cite the actual doc, not an adjacent doc with similar
name. INVARIANTS P2 single-authority-citation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): fix cursor PR #3127 BLOCKING contradictions + add §12 Q6

Cursor APPROVE_WITH_COMMENTS (/api/reviews/12093) caught two
substantive contradictions I introduced when adding TokenizedSource
in commit 2b9756b:

1. §4.3 vs §9 Step 2 signature mismatch — §4.3 said `-> TokenizedSource`
   but §9 Step 2 row still said `-> List<Token>`. Same
   `feedback_discipline_change_audit_all_contract_mentions` issue
   that's recurred 4x this session.

2. §4.3 referenced "§12 Q-new" but §12 only had Q1-Q5; broken anchor.

Fix:
1. §9 Step 2 row updated: signature `-> TokenizedSource` with
   wrapper carrier shape `{ tokens, diagnostics }` per §4.3
2. §4.3 anchor updated: "§12 Q6" (resolved)
3. Added §12 Q6: TokenizedSource carrier shape ratification —
   (a) wrapper record vs (b) per-Token diagnostic coupling;
   Director-recommend (a) for PB-3 SurfaceModule parallelism
4. §14 + §15 + §16 Q-list refs updated to Q1-Q6

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): fix codex BLOCKING PR #3127 — Token shape + Q4 audit boundary

Codex REQUEST_CHANGES (sha b881de2) with 2 substantive findings:

1. §4.1 Token shape claim "optional lexeme: String" — wrong per
   live substrate at src/v3/std/tokenize.dag:65-67. Live Token
   has 2 fields only (kind + span); lexeme-content lives ON the
   TokenKind variants (Ident(String) / IntLit(String) / etc.).

   Fix: corrected §4.1 to reflect live carrier shape; payloads
   on TokenKind variants noted explicitly.

2. §12 Q4 substrate-completeness audit scoped only to
   tokenize_generated.rs — missed the regen_tokenize codegen-
   driver boundary. If regen_tokenize carries scanner-logic
   decisions (rather than mechanical template-rendering of
   substrate facts), the substrate isn't complete — the driver
   IS hand-Rust scanner logic in disguise.

   Fix: Q4 audit extended with (d) regen_tokenize codegen-
   driver logic audit + (e) ROADMAP.md deferral row option per
   feedback_paper_shrink_variants P5 receipt discipline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): fix codex BLOCKING PR #3127 — TokenizeDiagnostic PROPOSED + scaffold disclosure

Codex REQUEST_CHANGES (sha b881de2, full body) caught 2 substantive
overstatements:

1. §2 line 46 claimed "tokenize failures produce typed
   TokenizeDiagnostic variants" — but live tokenize_generated.rs:96
   returns generic `Result<Vec<Token>, Diagnostic>` with
   `Diagnostic::TokenizerError { message, span, correction }`. Typed
   TokenizeDiagnostic is a PROPOSED extension, not live state.

   Fix: §2 reframed with live state explicit + TokenizeDiagnostic
   marked PROPOSED per PR #3077 §12 Q7 ratification path.

2. §1 line 22 + §6 + §9 Step 2 line 198 framed PB-2 as "mostly
   verification" — but live tokenize.dag:16-30+ has TWO explicit
   tracked scaffold zones:
   - SG-1a: regen_tokenize parses raw source text for
     dag_keyword_set / dag_operators (ValueBody::Unparsed)
   - Character-level under-consumption: StringEscapeSpec /
     LocalPunctSpec.pattern / string_literal_delimiter as opaque
     Strings; hidden Rust character predicates (byte.is_ascii_digit
     etc.) at tokenize_generated.rs:15-22 leaking through codegen

   Residual hand-Rust is NOT just the codegen artifact — it includes
   (a) regen_tokenize logic, (b) SG-1a raw-text-extractor scaffold,
   (c) character-predicate scaffold leaking through codegen.

   Fix: §1 + §6 + §9 Step 2 reframed honestly. PB-2 is "FURTHER
   ALONG but not complete"; Step 4 carries scaffold-retirement
   scope, not just codegen-artifact retirement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3127 BLOCKING (review id 12370) — drop TokenizedSource + cite concrete P5 receipts

Codex review id 12370 on sha d15e1f2 raised two load-bearing planning-shape
findings. Both addressed; this commit ports the same edits already living on
fix-forward branch docs/director-l25-postmerge-cleanups (PR #3138 commit
6adb992) onto PR #3127's branch directly so codex BLOCKING resolves on
this PR's own HEAD rather than waiting on PR #3138 merge.

Finding 1 — parallel boundary carriers (INVARIANTS P2 / Practices 3+5):
§4.3 + §9 Step 2 + §12 Q6 named `TokenizedSource { tokens, diagnostics }`
as the output, while §2/§7.2/§7.3 named `List<Token>`. Same misclassification
removed from the parse L2.5 (PR #3138 §4.3): tokenize sits in the fail-fast
output domain alongside PB-3 parse + PB-6 emit (a partial token list with a
corrupt token in the middle is not a valid downstream input for parse), so
the failure couples via `Result`, not into the structural carrier.

Resolution:
- §4.3 rewritten to ratify `Result<List<Token>, TokenizeDiagnostic>` — the
  live `tokenize_generated.rs:96` shape — with no `TokenizedSource` extension.
- §9 Step 2 row signature updated to match; explicit "single canonical
  boundary carrier: List<Token> on the Ok branch" framing.
- §12 Q6 resolved REJECTED in-doc (no operator ratification needed;
  disposition follows from the cross-stage discriminator load-bearing in
  PR #3138 parse L2.5).
- §16 memory-disciplines bullets rewritten parallel to PR #3138 parse §16:
  Result-sum, no diagnostics field on `List<Token>`.
- §14 "Surfaces awaiting" trimmed Q6 from the operator-ratification list.

Finding 2 — soft deferral of `regen_tokenize` retirement (INVARIANTS P5):
deferral previously named "PB-Bootstrap-Process lane scope" without a
concrete ROADMAP.md row. Updated §9 Step 2 + Step 4 rows to cite the named
receipts:
- `docs/design-pure-bootstrap-zero.md:116` (PB-Bootstrap-Process lane:
  author bootstrap.dag + generated trampoline; sized M).
- `docs/design-pure-bootstrap-zero.md:118-123` (N=0 runtime verification
  gates).
- ROADMAP.md:467 (Character-level under-consumption in tokenize + syntax
  authorities — phase-2 char-class retype owns the codegen-driver path).
- ROADMAP.md:416 (Class 5 Gap 3 — top-level `ValueBody` boundary; gating
  substrate-capability for the phase-2 retype).
- ROADMAP.md:53 (T-PB-A — non-test census → 0 floor).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3138 BLOCKING (sha f08b952) Finding 1 — bind to live CharClass authority

Porting the same fix that landed on PR #3138 commit 367fdc2 onto PR #3127's
own branch so codex BLOCKING resolves on this PR's HEAD directly.

Codex Finding 1: §4.2 TokenizeDiagnostic + §5.1/§5.2 headings used
`ScannerCharClass` / `ScannerClassRef` — names that exist only in the
generated Rust enum spelling, not as a .dag substrate declaration. Live
authority is `dsl/std/unicode.dag:62` `type CharClass = Whitespace | Digit
| IdentStart | IdentContinue`, consumed at `src/v3/compiler/tokenize.dag:103`.

Resolution:
- §4.2: `expected_class: ScannerClassRef` → `expected_class: CharClass`;
  dropped the `type ScannerClassRef = ScannerCharClass` alias; added
  codex-finding callout citing the substrate authority.
- §5.1: heading + intro now cite `dsl/std/unicode.dag:62` directly.
- §5.2: heading "CharClass → token-recognition state machine".

Same failure-mode as `feedback_grep_substrate_before_naming_ratification`:
naming a substrate carrier without grep-verifying against live .dag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3138 INLINE BLOCKING line:188 — §7.3 chain Ok-branch annotation

Same edit as PR #3138 commit a8c0ff7 ported to this PR's branch. §7.3
cross-stage chain now annotates Ok-branch propagation + Err-branch
fail-fast termination explicitly, eliminating the apparent contradiction
between §4.3 (Result-sum) and §7.3 (List<Token> in the chain). They were
already consistent — Ok-branch payload flows forward; Err terminates —
but the annotation makes it self-evident at §7.3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): openai-pro PR #3127 BLOCKING (sha d15e1f2) — character-level scaffold dissolution trigger

Same edit as PR #3138 commit 5a93d93 ported to this PR's branch.
§1 item 2 character-level under-consumption scaffold now carries the
same SG-1a-shape dissolution trigger structure: substrate-consumption
condition (a) + codegen-driver condition (b) + same-PR delete receipt,
with cross-refs to §9 Step 4 gating prereqs already cited.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3127 APPROVE_WITH_COMMENTS — §14 + §15 Q6-already-rejected sweep

Same edit as PR #3138 commit 887c696 ported to this PR's branch. §14
acceptance criterion 11 + §15 step 1 now say "Q1-Q5" with explicit
Q6-rejected crossrefs, aligning with §12 Q6 + §14 "Surfaces awaiting"
which already said "Q1-Q5 only".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls
briansrls merged commit 5d9b409 into main May 15, 2026
3 checks passed

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review metadata

  • Provider / model: codex / unknown
  • Commit: 887c6967 · Trigger: schedule
  • Thinking: 333s wall

BLOCKING (5)

Root Cause

  • docs/design-infer-stage-l25-model.md Cross-stage Decision 2.B trigger prose was copied into the InferDiagnostic per-stage scaffold → make the trigger infer.rs-only and leave parse/lower coverage to their own per-stage carriers/Q7 mapping.
  • docs/design-parse-stage-l25-model.md Result-sum diagnostic refactor split record-vs-kind shape but omitted the coproduct receipt on the kind sums → mark ParseDiagnosticKind and TokenizeDiagnostic as 🟡 scaffold with the Step 2 full-site enumeration trigger or justify a 🟢 terminal ledger.
  • docs/design-tokenize-stage-l25-model.md Post-merge Q7 gate reconciliation was applied to the parse sequence but not to all downstream status/surfaces-awaiting sections → mark Q7 DONE consistently or remove it from awaiting gates.

⚠️ The main shape is much cleaner, but these doc-authority contradictions and missing coproduct receipts should be fixed before the L2.5 docs become worker-brief authority.

// substrate coproducts require 🟢/🟡/🔴 classification + dissolution trigger.
//
// **Dissolution trigger**: when Step 2 worker brief enumerates the full
// variant set against `parse_generated.rs` Diagnostic::ParseError, lower.rs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BLOCKING: InferDiagnostic's scaffold trigger requires enumerating parse and lower diagnostic sites for an infer-only sum, which violates P2 single-authority/layer discipline by making a per-stage carrier depend on sibling-stage authorities.

// Optional: additional context fields per Step 2 brief enumeration
}

type ParseDiagnosticKind

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BLOCKING: ParseDiagnosticKind is a proposed substrate coproduct with multiple variants but has no 🟢/🟡/🔴 Practice 4 classification or named dissolution trigger.

// fixed in PR #3138). TokenizeDiagnostic references the live `CharClass`
// directly.

type TokenizeDiagnostic

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BLOCKING: TokenizeDiagnostic is a proposed substrate coproduct with multiple variants but has no 🟢/🟡/🔴 Practice 4 classification or named dissolution trigger.

2. **PM amends close plan** to route through PB-X lanes + cite this doc as PB-3 L2.5 substrate
3. **PM amends §1.8** with PB-3 gate row citing this doc
4. **PR #3077 §12 Q7 ratifies** (cross-stage Decision 2.B extension path) — affects PB-3 ParseDiagnostic shape
4. **PR #3077 §12 Q7 ratifies** (cross-stage Decision 2.B extension path) — affects PB-3 ParseDiagnostic shape. **DONE 2026-05-15T00:21:19Z** when PR #3077 (PB-4 lower L2.5) merged; Q7 ratification carried in that merge. The §6 / §7.2 "Step 2 must wait on Q7" gate is therefore now satisfied — Step 2 brief authoring is genuinely unblocked, not just procedurally listed as the next step.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BLOCKING: This line marks PR #3077 §12 Q7 DONE, but the same file still lists Q7 under §16 Surfaces awaiting, leaving the Step 2 gate internally contradictory.


**Surfaces awaiting**:
- Operator/PM ratification on §12 Q1–Q5 (Q6 resolved REJECTED in-doc per codex PR #3127 BLOCKING — no ratification needed)
- PR #3077 §12 Q7 ratification (cross-stage Decision 2.B extension path)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BLOCKING: The new PB-2 doc still lists PR #3077 §12 Q7 ratification as awaiting even though the sibling PB-3 doc says that gate merged on 2026-05-15T00:21:19Z, so worker sequencing remains stale.

briansrls added a commit that referenced this pull request May 15, 2026
…ross 3 L2.5 docs

Codex review id (sha 887c696, 333s thinking) flagged three findings,
all `feedback_discipline_change_audit_all_contract_mentions` recurrences
where partial sweeps left §-internal contradictions.

Finding 1 — infer doc cross-stage trigger leak:
§4.2 InferDiagnostic dissolution trigger said "when Step 2 worker brief
enumerates the full variant set against `parse_generated.rs`
Diagnostic::ParseError, lower.rs Diagnostic construction sites, and
infer.rs Dag::mark_unresolved emission sites." That cross-stage trigger
surface is wrong for the infer-specific scaffold. Narrowed to infer-only:
"against `src/v3/compiler/src/infer.rs` Diagnostic construction sites +
`Dag::mark_unresolved` emission sites (infer-stage only)." Parse and lower
have their own per-stage carriers + own Q7 mapping; this doc no longer
reaches into their dissolution-trigger surface.

Finding 2 — parse + tokenize coproduct receipts:
`ParseDiagnosticKind` (parse §4.2) and `TokenizeDiagnostic` (tokenize §4.2)
sums were declared without the 🟡 SCAFFOLD / 🟢 TERMINAL classification +
dissolution trigger that the infer doc carries (per modeling-discipline
Practice 4 + `feedback_coproduct_dissolution`). Added matching scaffold
receipts to both: 🟡 SCAFFOLD at PROPOSED stage with stage-local dissolution
trigger (Step 2 brief enumerates against parse_generated.rs / tokenize_generated.rs
Diagnostic::* construction sites — stage-only, not cross-stage); promote
to 🟢 TERMINAL when full variant set lands. Both also carry the anti-bridge
note per Q6.5.

Finding 3 — tokenize Q7 reconciliation:
The parse doc has the "Q7 DONE 2026-05-15T00:21:19Z" annotation at §15 step 4
(commit f85fa1f) but the tokenize doc still framed Q7 as a pending lane
dependency at §4.2 line:113 ("Lane dependency"), §15 step 3, and §14
"Surfaces awaiting". Annotated all three:
- §4.2 "Lane dependency": Q7 DONE timestamp + "TokenizeDiagnostic per-stage
  variant authoring is the remaining lane work."
- §15 step 3: full DONE annotation matching parse doc §15 step 4 shape +
  cross-ref to the parse doc.
- §14 "Surfaces awaiting": strikethrough + DONE annotation.

PR #3127 also carries the tokenize doc; same edits will port there in a
companion commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 15, 2026
Same edits as PR #3138 commit e9739ea's tokenize-doc portion ported to
this PR's branch.

Finding 2 — TokenizeDiagnostic coproduct receipt:
Added 🟡 SCAFFOLD classification + dissolution trigger (tokenize-stage only:
Step 2 enumerates against tokenize_generated.rs:96 Diagnostic::* sites) +
anti-bridge note per Q6.5.

Finding 3 — Q7 reconciliation:
§4.2 "Lane dependency", §15 step 3, and §14 "Surfaces awaiting" now all
annotate Q7 as DONE 2026-05-15T00:21:19Z (PR #3077 merge timestamp);
TokenizeDiagnostic per-stage variant authoring is the remaining lane work.

(Finding 1 — infer-doc cross-stage trigger leak — does not apply to this
branch; it lives on PR #3138's branch which carries the infer L2.5 doc.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Status reply for the inline BLOCKING at docs/design-infer-stage-l25-model.md:150 (codex sha 887c696 Finding 1). Already addressed in commit e9739ea on this branch (3-finding sweep). Current state at HEAD:

The §4.2 InferDiagnostic dissolution trigger no longer reaches into parse-stage or lower-stage diagnostic sites. The trigger is now infer-only:

"Dissolution trigger: when Step 2 worker brief enumerates the full variant set against src/v3/compiler/src/infer.rs Diagnostic construction sites + Dag::mark_unresolved emission sites (infer-stage only) — promote to 🟢 TERMINAL at the per-stage diagnostic-variant scope. Parse-stage and lower-stage coverage are NOT part of this trigger: they live in their own per-stage carriers (ParseDiagnostic per PR #3138 PB-3 parse L2.5 §4.2, lower-stage diagnostics per PB-4 lower L2.5 §4.2) and their own Q7 mapping."

Same commit also adds the missing 🟡 SCAFFOLD coproduct receipts to ParseDiagnosticKind and TokenizeDiagnostic (Finding 2) and reconciles the tokenize doc's Q7 status (Finding 3 — Q7 DONE 2026-05-15T00:21:19Z annotation at §4.2 + §15 step 3 + §14 "Surfaces awaiting"). PR HEAD is now e9739ea; dashboard please retally — 887c696 is one push stale.

— sent from zesty-bear-812

@briansrls

Copy link
Copy Markdown
Contributor Author

Status reply for the inline BLOCKING at docs/design-parse-stage-l25-model.md:123 (codex sha 887c696 Finding 2 — same review I already responded to inline on infer.dag:150). Already addressed in commit e9739ea on this branch.

At HEAD, ParseDiagnosticKind (and TokenizeDiagnostic per the same finding) now carry the 🟡 SCAFFOLD classification + dissolution trigger per modeling-discipline Practice 4 + feedback_coproduct_dissolution:

"🟡 SCAFFOLD coproduct at PROPOSED stage. ... Dissolution trigger: when Step 2 worker brief enumerates the full variant set against src/v3/compiler/src/parse_generated.rs:138 Diagnostic::* construction sites (parse-stage only — not cross-stage), promote to 🟢 TERMINAL at the per-stage diagnostic-variant scope. ... PR #3077 §12 Q7 ratification (DONE 2026-05-15T00:21:19Z per §15 step 4) determines whether this stays per-stage sum (option b) or extends shared Diagnostic (option a). ... Anti-bridge: per Q6.5 anti-bridge invariant at diagnostics.dag:135-141, ParseDiagnosticKind does NOT collapse into CompilerDiagnosticKind without substrate-extension ratification."

PR HEAD is now e9739ea. Dashboard appears to be caching the older 887c696 sha — git ls-remote confirms the push landed on origin.

— sent from zesty-bear-812

@briansrls

Copy link
Copy Markdown
Contributor Author

Status reply for the inline BLOCKING at docs/design-tokenize-stage-l25-model.md:106 (codex sha 887c696 Finding 2, tokenize-doc side — same finding-class as the parse-doc inline at line 123 I responded to ~1 min ago). Already addressed in commit e9739ea on this branch (and ported to PR #3127 commit 10c89fd).

At HEAD, TokenizeDiagnostic carries the matching 🟡 SCAFFOLD classification + dissolution trigger:

"🟡 SCAFFOLD coproduct at PROPOSED stage. ... Dissolution trigger: when Step 2 worker brief enumerates the full variant set against src/v3/compiler/src/tokenize_generated.rs:96 Diagnostic::* construction sites (tokenize-stage only — not cross-stage), promote to 🟢 TERMINAL at the per-stage diagnostic-variant scope. ... PR #3077 §12 Q7 ratification (DONE 2026-05-15T00:21:19Z — see §15 step 3 + §14 "Surfaces awaiting") determines whether this stays per-stage sum (option b) or extends shared Diagnostic (option a). ... Anti-bridge: per Q6.5 anti-bridge invariant at diagnostics.dag:135-141, TokenizeDiagnostic does NOT collapse into CompilerDiagnosticKind without substrate-extension ratification."

3 inlines from codex's sha 887c696 5-finding BLOCKING (infer.dag:150, parse.dag:123, tokenize.dag:106) all map to Findings 1 + 2 + 3 — all addressed at HEAD e9739ea / 10c89fd.

— sent from zesty-bear-812

briansrls added a commit that referenced this pull request May 15, 2026
…iting Q7 contradiction

Cursor inline at sha 887c696 caught the symmetric finding to the codex
5-finding BLOCKING #3: parse-doc §15 step 4 already annotated Q7 as DONE
(commit f85fa1f) but parse-doc §16 "Surfaces awaiting" still listed Q7
as pending. Same `feedback_discipline_change_audit_all_contract_mentions`
sweep failure — the tokenize doc had three sites carrying the pending
framing (commit e9739ea fixed those) but the parse doc's §16 site was
missed in the original Q7-DONE sweep.

Resolution: §16 bullet now strikes through + "DONE 2026-05-15T00:21:19Z
(PR #3077 merged carrying Q7 ratification; see §15 step 4)" — same shape
as the tokenize doc's §14 "Surfaces awaiting" Q7-DONE annotation landed
in e9739ea.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@briansrls

Copy link
Copy Markdown
Contributor Author

Status reply for the inline BLOCKING at docs/design-tokenize-stage-l25-model.md:366 (cursor on sha 887c696 — same finding-class as the parse-doc §16 inline at line 372). Already addressed in commit e9739ea on this branch (and ported to PR #3127 commit 10c89fd).

At HEAD, the "Surfaces awaiting" Q7 entry shifted to line 382 due to inserted scaffold-receipt content; the line reads:

"- PR #3077 §12 Q7 ratification (cross-stage Decision 2.B extension path) — DONE 2026-05-15T00:21:19Z (PR #3077 merged carrying Q7 ratification; see §15 step 3)"

§15 step 3 (line 340) also has the full DONE annotation matching the parse doc's §15 step 4 shape. §4.2 "Lane dependency" (line 129) likewise annotates Q7 as DONE. Three Q7-DONE sites on the tokenize doc now agree internally — matches the parse doc's three-site coverage (§7.2 + §15 step 4 + §16) post commit 4879685.

No worker-sequencing staleness remains; the gate is satisfied by repo state.

— sent from zesty-bear-812

briansrls added a commit that referenced this pull request May 15, 2026
…r inline Q7 sweep (#3140)

* docs(r3): PB-2 tokenize pipeline-stage L2.5 domain model — DRAFT for ratification

Director-tier L2.5 model for PB-2 tokenize per operator 2026-05-14
ratification (Decision 1.A scoping = Option A).

PB-2 is the FURTHEST-ALONG pipeline stage — substrate authority
already lives in `.dag`:
- src/v3/std/tokenize.dag (Token + TokenKind taxonomy; LIVE 143
  lines)
- src/v3/compiler/tokenize.dag (tokenizer implementation; LIVE
  154 lines)
- src/v3/compiler/src/tokenize_generated.rs (AUTO-GENERATED; 362
  lines)

This is the END STATE that all other pipeline-stage migrations
target. PB-2 L2.5 is correspondingly lighter — mostly verification
+ residual hand-Rust retirement, NOT new substrate authoring.

Distinct §9 4-step framing:
- Step 3 = VERIFY substrate completeness (audit per
  feedback_paper_shrink_variants)
- Step 4 = HANDOFF/RETIRE residual hand-Rust scaffolding
  (coordinates with PB-Bootstrap-Process lane for codegen-driver
  retirement)

Captures audit dimensions explicitly:
- scanner-class definitions = declarative byte-pattern membership
- recognition tables = closed-axis enums
- state machine = structural transitions
- no V2 `pub mod tokenize` absorption check

§12 Q1: codegen-driver retirement scope — Director-recommend
PB-Bootstrap-Process handles all codegen-driver retirement
cross-cuttingly (not per-stage paper-shrink risk).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): §12.6 citation fix — tokenize is PB-2 lane scope per design-pure-bootstrap-zero.md

Per cursor PR #3085 finding: §12.6 explicitly tables only 4
pipeline-stage migrations (emit→lower→infer→parse); tokenize is
per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085
commit 89fbd7a applied here.

INVARIANTS P1 — documentation must not overstate authority cites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): preemptive fix for PR #3126 codex BLOCKING propagation — PB-2 live state honesty

Same class as codex INLINE BLOCKING #3126 finding 1 (live state
honesty for diagnostic coupling) applied preemptively to PB-2
tokenize L2.5.

PB-2 §4.3 had "diagnostics coupled INTO List<Token>" framing
which would overstate the live carrier shape (bare List<Token>
has no diagnostic field; tokenize_generated.rs:96 today returns
Result<Vec<Token>, Diagnostic>).

Fix: §4.3 reframed with PROPOSED substrate extension explicit —
new `TokenizedSource { tokens, diagnostics }` wrapper carrier as
the typed-state output. Step 2 brief includes wrapper authoring
in pipeline-slot PR scope.

Same discipline as PR #3126 commit bdff8c5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3077 — fix PB-2 lane citation (design-pure-bootstrap.md not -zero.md)

Per cursor APPROVE_WITH_COMMENTS /api/reviews/12087: PB-2 lane is
defined in docs/design-pure-bootstrap.md §"PB-2 — tokenize retire"
(line ~134), NOT docs/design-pure-bootstrap-zero.md. The -zero.md
doc has Subsumed-lanes list with PB-1/PB-4/PB-5/PB-6 but NOT PB-2.

Propagated fix applies same cite-error correction as PR #3066 §1.8
discipline: cite the actual doc, not an adjacent doc with similar
name. INVARIANTS P2 single-authority-citation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): fix cursor PR #3127 BLOCKING contradictions + add §12 Q6

Cursor APPROVE_WITH_COMMENTS (/api/reviews/12093) caught two
substantive contradictions I introduced when adding TokenizedSource
in commit 2b9756b:

1. §4.3 vs §9 Step 2 signature mismatch — §4.3 said `-> TokenizedSource`
   but §9 Step 2 row still said `-> List<Token>`. Same
   `feedback_discipline_change_audit_all_contract_mentions` issue
   that's recurred 4x this session.

2. §4.3 referenced "§12 Q-new" but §12 only had Q1-Q5; broken anchor.

Fix:
1. §9 Step 2 row updated: signature `-> TokenizedSource` with
   wrapper carrier shape `{ tokens, diagnostics }` per §4.3
2. §4.3 anchor updated: "§12 Q6" (resolved)
3. Added §12 Q6: TokenizedSource carrier shape ratification —
   (a) wrapper record vs (b) per-Token diagnostic coupling;
   Director-recommend (a) for PB-3 SurfaceModule parallelism
4. §14 + §15 + §16 Q-list refs updated to Q1-Q6

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): fix codex BLOCKING PR #3127 — Token shape + Q4 audit boundary

Codex REQUEST_CHANGES (sha b881de2) with 2 substantive findings:

1. §4.1 Token shape claim "optional lexeme: String" — wrong per
   live substrate at src/v3/std/tokenize.dag:65-67. Live Token
   has 2 fields only (kind + span); lexeme-content lives ON the
   TokenKind variants (Ident(String) / IntLit(String) / etc.).

   Fix: corrected §4.1 to reflect live carrier shape; payloads
   on TokenKind variants noted explicitly.

2. §12 Q4 substrate-completeness audit scoped only to
   tokenize_generated.rs — missed the regen_tokenize codegen-
   driver boundary. If regen_tokenize carries scanner-logic
   decisions (rather than mechanical template-rendering of
   substrate facts), the substrate isn't complete — the driver
   IS hand-Rust scanner logic in disguise.

   Fix: Q4 audit extended with (d) regen_tokenize codegen-
   driver logic audit + (e) ROADMAP.md deferral row option per
   feedback_paper_shrink_variants P5 receipt discipline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): fix codex BLOCKING PR #3127 — TokenizeDiagnostic PROPOSED + scaffold disclosure

Codex REQUEST_CHANGES (sha b881de2, full body) caught 2 substantive
overstatements:

1. §2 line 46 claimed "tokenize failures produce typed
   TokenizeDiagnostic variants" — but live tokenize_generated.rs:96
   returns generic `Result<Vec<Token>, Diagnostic>` with
   `Diagnostic::TokenizerError { message, span, correction }`. Typed
   TokenizeDiagnostic is a PROPOSED extension, not live state.

   Fix: §2 reframed with live state explicit + TokenizeDiagnostic
   marked PROPOSED per PR #3077 §12 Q7 ratification path.

2. §1 line 22 + §6 + §9 Step 2 line 198 framed PB-2 as "mostly
   verification" — but live tokenize.dag:16-30+ has TWO explicit
   tracked scaffold zones:
   - SG-1a: regen_tokenize parses raw source text for
     dag_keyword_set / dag_operators (ValueBody::Unparsed)
   - Character-level under-consumption: StringEscapeSpec /
     LocalPunctSpec.pattern / string_literal_delimiter as opaque
     Strings; hidden Rust character predicates (byte.is_ascii_digit
     etc.) at tokenize_generated.rs:15-22 leaking through codegen

   Residual hand-Rust is NOT just the codegen artifact — it includes
   (a) regen_tokenize logic, (b) SG-1a raw-text-extractor scaffold,
   (c) character-predicate scaffold leaking through codegen.

   Fix: §1 + §6 + §9 Step 2 reframed honestly. PB-2 is "FURTHER
   ALONG but not complete"; Step 4 carries scaffold-retirement
   scope, not just codegen-artifact retirement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): post-merge fix-forward — §16 + §9 Step 2 internal contradictions

Two post-merge doc-internal contradictions caught by reviewers
after operator merged PR #3077 / #3126 / #3085 at 2026-05-15T00:21Z.

**PR #3077 PB-4 lower §16 fix**:
§16 "Memory disciplines applied" bullet said "diagnostics coupled
INTO PreInferDag via biconditional" — but §4.3 (per openai-pro
DiagnosticAnchor fix commit b812db9) constrains biconditional
to PortAnchor-only. Other anchor kinds (DeclarationAnchor /
RecordFieldAnchor / SurfaceFormAnchor) couple without port-state.
Fix: §16 bullet honors §4.3 anchor-typed framing.

**PR #3126 PB-3 parse §9 Step 2 fix**:
§9 Step 2 row described diagnostics as "coupled INTO SurfaceModule"
as if live — §4.3 correctly marks it PROPOSED. Same
feedback_discipline_change_audit_all_contract_mentions pattern
that's recurred this session.
Fix: §9 Step 2 row clarified — "PROPOSED extension per §4.3";
Step 2 PR scope includes authoring the diagnostics field
extension, NOT a live coupling.

Per feedback_discipline_change_audit_all_contract_mentions: when
a substantive fix changes a discipline framing, audit ALL sections
(framing + contract + handoff). Post-merge audit surfaced these
residual contradictions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): post-merge fix-forward — PR #3126 codex BLOCKING (GrammarSpec parallel-authority + fail-closed weakening)

Codex REQUEST_CHANGES on already-merged PR #3126 (/api/reviews/12175):
2 substantive findings on the post-merge doc.

**Finding 1 (P2 violation — GrammarSpec parallel authority)**:

§3.2 says GrammarSpec is compile-time-only, NOT runtime-
interpreted (per Decision 3.B (b) operator override). But the
proposed stage contract still took `grammar: GrammarSpec` as
runtime input. Creates two authorities (compiled parser tables
+ runtime GrammarSpec value).

Fix: §4.3 signature reframed to `fn parse(tokens: List<Token>)
-> Result<SurfaceModule, ParseDiagnostic>` — NO runtime
GrammarSpec input. Compile-time generated parser tables consumed
via internal dispatch. Step 2 + Step 4 rows updated.

**Finding 2 (P3 + Practices 1/2 — fail-closed weakening)**:

Live parser at parse_generated.rs:138 returns `Result<SurfaceModule,
Diagnostic>` (fail-closed; aborts on first error). Earlier draft
proposed `SurfaceModule` with embedded diagnostics — would let
partial-parse states be constructible + let downstream observe
"success" output after parse failure. Violation of fail-closed
discipline.

Fix: signature preserves Result-sum (matches live + emit's
pattern). Distinguished cross-stage:
- Result-sum (parse + emit): fail-fast output domain
- Typed-state-with-coupled-diagnostics (lower + infer): structural
  output domain where partial-failure IS valid intermediate

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 post-merge APPROVE_WITH_COMMENTS — §4.1 + §16 fail-closed honesty

Cursor caught 2 more post-merge contradictions on PR #3126:

1. §4.1 line 81 "construction-time invariant" talks about
   "ParseDiagnostic in the diagnostic stream" tied to SurfaceModule
   path — but §5.2 + live parse_generated.rs:138 use
   Result<SurfaceModule, Diagnostic>. §4.1 reads as claim about
   today's plumbing.

   Fix: §4.1 reframed — live boundary explicit (Result-sum);
   construction-time invariant scoped to Ok-arm SurfaceModule +
   Err-arm ParseDiagnostic, no partial-parse with embedded
   diagnostics.

2. §16 line 397 cites C-8 as "ParseDiagnostic coupled INTO
   SurfaceModule" without qualifier — but §4.3 (post codex
   REQUEST_CHANGES fix) constrains to Result-sum.

   Fix: §16 bullet honors §4.3 Result-sum framing; cross-stage
   discriminator named.

Same recurring feedback_discipline_change_audit_all_contract_mentions
pattern — substantive fix to §4.3 + §9 Step 2 left §4.1 + §16
inconsistent. Post-merge audit catches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3085 INLINE BLOCKING — TypeConnective extension stop-signal

Cursor INLINE BLOCKING caught §3.2 line 66 "rules extend
automatically" weakens substrate-extension stop-signal. Thesis
discipline: a 7th TypeConnective variant requires explicit C1
audit + named infer-rule receipt.

Fix: §3.2 reframed. New TypeConnective variants do NOT extend
automatically; require explicit C1 substrate-extension audit +
named infer-rule receipt for the new variant's structural
inference behavior.

Per-variant structural facts means new variants need new
per-variant facts, NOT silent inheritance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3085 INLINE BLOCKING — AlgebraAxis + InferDiagnostic Practice 4 classification

Cursor INLINE BLOCKING /api/reviews/12218 (line:112): proposed
substrate coproducts (AlgebraAxis + InferDiagnostic) lack
🟢/🟡/🔴 classification + ledger/trigger per modeling-discipline
Practice 4 (Coproduct dissolution).

Fix: added 🟡 SCAFFOLD classification + named dissolution
trigger for both:

AlgebraAxis 🟡 SCAFFOLD:
- Trigger: Step 2 brief enumerates full algebra-axiom set
  against infer.rs check sites + verifies coverage parity
  with live verification.dag:146 AlgebraicLawKind 3-variant
  subset → promote to 🟢 TERMINAL.

InferDiagnostic 🟡 SCAFFOLD:
- Trigger: Step 2 brief enumerates full variant set against
  parse_generated.rs / lower.rs / infer.rs diagnostic emission
  sites → promote to 🟢 TERMINAL.
- Anti-bridge per Q6.5: does NOT collapse into
  CompilerDiagnosticKind without substrate-extension
  ratification per PR #3077 §12 Q7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3077 INLINE BLOCKING — §5.1 SurfaceItem allocation correction

Cursor INLINE BLOCKING /api/reviews/12251 line:130: §5.1 said
"every SurfaceItem variant maps 1:1 to a Declaration placeholder"
but live lower.rs:2950-2958 explicitly skips Let/Module/Import
in collect_symbols.

Verified via Read of lower.rs:2956-2958:
  SurfaceItem::Let { .. } => continue,
  SurfaceItem::Module { .. } => continue,
  SurfaceItem::Import { .. } => continue,

Fix: §5.1 reframed — DeclarationAllocating variants (Fn /
FnExternalBody / Data / TypeAtom / TypeRecord) map to
placeholders; NonDeclarationAllocating variants (Let / Module /
Import) skip allocation per live lower.rs behavior.

Let-bodies lower to Bind expressions in Pass 2; Module/Import
are parsed-facts preserved but un-declared.

Earlier "every SurfaceItem variant" framing overstated; would
have steered Step 2/3 worker into wrong allocation contract.
Per INVARIANTS P1/P2 live-state honesty + facts-flow-forward.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3077 INLINE BLOCKING — ElaborationSpec scope broadened

Cursor INLINE BLOCKING line:33: ElaborationSpec was defined only
as Surface→Behavior recipe mapping, but lower constructs
Declarations / TypeConnectives / BranchPatterns / Bindings as
well. Non-Behavior lowering decisions outside declared authority
violates THESIS substrate ownership + INVARIANTS P2.

Fix: §3.2 ElaborationSpec scope broadened to ALL lowering
decisions:

1. SurfaceItem → Declaration recipes (Fn / Data / Type variants +
   Let/Module/Import skip-allocation per §5.1)
2. SurfaceType → TypeConnective recipes (Atom / Arrow / Compose /
   Disj construction)
3. SurfaceExpr → Behavior recipes (Value / Transform / Branch /
   Loop / Bind construction)
4. SurfacePattern → BranchPattern recipes (ResolvedVariant /
   UnresolvedVariant / record-pattern construction)
5. Binding-site rules (Bind params + result_port construction)

ElaborationSpec is single-authority across ALL axes; no axis
lives in implementation-tier hand-Rust.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — §7.1 ordering vs independence clarification

Cursor APPROVE_WITH_COMMENTS /api/reviews/12265 line 197: §7.1
mixed two claims:
- "parse migrates AFTER tokenize substrate-side stable" (ordering)
- "PB-3 parse migration is independent of PB-2 tokenize migration
  status" (independence)

Read as contradictory by reviewers. Need one coherent story.

Fix: §7.1 reframed with two distinct axes explicit:

1. Substrate-stability ordering (SELF_HOSTING.md §2 bottom-up):
   tokenize Token carrier shape must be stable BEFORE parse
   migrates. Already true at HEAD (tokenize.dag:65-67 declares
   live carrier). ✓

2. Migration-timing independence (parallel-dispatch axis): PB-3
   parse migration ships in parallel with PB-2 residual-retirement
   work (SG-1a + character-level scaffold + codegen-driver
   retirement per PB-2 L2.5 §1). What parse needs is the stable
   Token CARRIER; PB-2's migration is about retiring residual
   hand-Rust, not changing the carrier.

Both claims coherent on the axis split; not contradictory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING — ParseDiagnostic SourceSpan structural requirement

Cursor INLINE BLOCKING /api/reviews/12277 line:65: ParseDiagnostic
variants like UnexpectedToken lacked SourceSpan field;
List<ParseDiagnostic> cannot satisfy fail-closed source
attribution structurally without span on every variant.
INVARIANTS P2/P3 violation.

Fix: every ParseDiagnostic variant now carries SourceSpan
structurally:
- UnexpectedToken: added span: SourceSpan
- UnterminatedConstruct: opener_span: SourceSpan (already present)
- InvalidLiteral: added span: SourceSpan
- DuplicateRecordFieldLabel: added span: SourceSpan (current site)
  + prior_span: SourceSpan (prior site; both required)

Per INVARIANTS P2/P3 fail-closed source attribution discipline:
every diagnostic emission carries structural source-span
provenance; not optional.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING — Token authority cite phantom-reference fix

Cursor INLINE BLOCKING /api/reviews/12279 line:29: §3.1 cited
`src/v3/compiler/src/tokenize.rs` as "current hand-Rust" for
Token carrier — but `tokenize.rs` (without _generated suffix)
doesn't exist. Live state has tokenize.dag (live substrate) +
tokenize_generated.rs (codegen artifact).

Per design-pure-bootstrap.md PB-2 lane: tokenize retire has
substantially landed. The reference was an earlier-draft
phantom from when Token-was-hand-Rust framing was the assumption.

Fix: §3.1 reframed — Token type lives in LIVE
src/v3/std/tokenize.dag:65-67 shared taxonomy; tokenizer
implementation also live at src/v3/compiler/tokenize.dag (154
lines); codegen artifact at tokenize_generated.rs. tokenize.rs
phantom reference removed explicitly. PB-2 substantially landed
per design-pure-bootstrap.md; residual scaffold-retirement
scope per PB-2 L2.5 PR #3127.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING — Step 2 pipeline-slot target fix (compiler.dag → pipeline.dag)

Cursor INLINE BLOCKING /api/reviews/12281 line:138: §9 Step 2
referenced generic "compiler.dag" but dsl/gunbc/compiler.dag:24
explicitly directs internal pipeline (Tokenize → Parse → ...)
to src/v3/compiler/pipeline.dag, NOT generic compiler.dag.

Worker briefs authored against this doc would target the wrong
file for pipeline-slot declaration. P2 single-authority violation.

Fix: §9 Step 2 row in ALL 4 L2.5 docs (PB-2 / PB-3 / PB-4 / PB-5)
updated:
- "declared in compiler.dag" → "declared in src/v3/compiler/pipeline.dag (per dsl/gunbc/compiler.dag:24 — internal pipeline lives in pipeline.dag, NOT generic compiler.dag)"
- substrate column: "compiler.dag refinement" → "pipeline.dag refinement"
- §13 "Step 2 (pipeline-slot in compiler.dag)" → "pipeline-slot in src/v3/compiler/pipeline.dag"

Same phantom-citation class as the tokenize.rs phantom (commit
8ae37b4): I cited generic file path without verifying which
specific file is authoritative per project structure. Should
have grep'd dsl/gunbc/compiler.dag header notes before authoring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING — Step 3b/4 phasing P5 receipt unambiguity

Cursor INLINE BLOCKING /api/reviews/12283 line:181: Q5 said
Step 3b "full parser body .dag migration + parser body deletion
in same PR", but §15 sequence schedules Step 4 parity/deletion
AFTER Step 3b merges. P5 dissolution receipt ambiguous.

If Step 3b lands .dag parser body BEFORE Step 4 deletes Rust
parse() body, Rust + .dag parser bodies coexist temporarily —
paper-shrink-relocation risk per feedback_paper_shrink_variants.

Fix:
1. §9 Step 3b row reframed as "Step 3b/4 COMBINED" — atomic
   single PR (full .dag parser body + parity TestClaim +
   parse_generated.rs:138 deletion + census shrink). Cannot land
   .dag parser body before Rust deletion.
2. §12 Q5 phasing clarified:
   - Phase 3a (separate PR): grammar table extension; P5 receipt
     = ROADMAP deferral row naming Step 3b/4 as future-receipt
   - Phase 3b/4 COMBINED (single PR): atomic substrate substitution
3. §9 + §15 update notes: sequence collapses steps 12-17 into
   single dispatch+merge for combined phase

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3126 high-level BLOCKING findings 1 + 2

Codex high-level BLOCKING (sha 140eb6b) had 4 findings:
- Findings 3 + 4 already addressed in PR #3138 commits 0159773
  + a1607a8
- Findings 1 + 2 addressed in this commit

**Finding 1 (Diagnostic kind/record conflated)**:
§4.2 ParseDiagnostic was modeled as variants-directly with span
+ kind-fields mixed. Live Diagnostic at diagnostics.dag:150 uses
record-wraps-kind pattern (`{ kind, span, message, correction }`).
Need consistent shape.

Fix: refactored to record-wraps-kind:
- `type ParseDiagnostic { kind: ParseDiagnosticKind, span: SourceSpan }`
- `type ParseDiagnosticKind = UnexpectedToken | UnterminatedConstruct | InvalidLiteral | DuplicateRecordFieldLabel | ...`

Span lives on ParseDiagnostic record (single source of truth);
variant-specific spans (opener_span / prior_span) remain on kind
variants where meaningful.

**Finding 2 (PB-2 §6 obsolete sibling-lane assumption)**:
§6 line 198 said "PB-2 Tokenize | src/v3/std/tokenize.dag (NEW
per PB-2 L2.5)" — but tokenize.dag is ALREADY LIVE per
design-pure-bootstrap.md §"PB-2 — tokenize retire" (substantially
landed).

Fix: §6 prereq table row updated to reflect LIVE state. PB-2's
residual scope is scaffold-retirement (SG-1a + character-level +
codegen-driver per PB-2 L2.5 §1), not carrier authoring. PB-3
consumes the live Token carrier; carrier shape stable across
PB-2 residual-retirement timing.

Findings 3 + 4 already addressed:
- Finding 3 (pipeline.dag target): commit 0159773
- Finding 4 (Step 3b/4 atomic vs sequential): commit a1607a8

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — phantom "module-level metadata" removed

Cursor APPROVE_WITH_COMMENTS line:79: §4.1 said "SurfaceModule
(verified live) carries List<SurfaceItem> + module-level
metadata" — but live parse_surface.dag:29 has ONLY
`{ items: List<SurfaceItem> }`. No metadata fields.

Phantom addition violated INVARIANTS P1 live-state honesty.

Fix: §4.1 reframed to match live carrier exactly. Same
phantom-addition class as tokenize.rs phantom (commit 8ae37b4).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3085 high-level BLOCKING findings — AtomPayload 5-variant + diagnostic-table PROPOSED

Codex high-level BLOCKING (sha bf4d315) — 2 substantive findings:

**Finding 1 (AtomPayload stale)**:
§2 + §5 cited infer.rs:10 top-comment "Atom(Identifier { name,
resolved })" — but live substrate.dag:87 has 5-variant
AtomPayload sum: Literal | UnresolvedIdentifier |
ResolvedByStructure | ResolvedByName | TypeParam.

infer.rs top-comment is STALE vs live substrate. My doc inherited
the drift.

Fix: §2 enumeration corrected to all 5 AtomPayload variants per
live substrate.dag:87.

**Finding 2 (diagnostic-table PROPOSED, not live)**:
§2 + §4.1 + §4.3 said "diagnostics.contains(port_id)
biconditional" as if live — but Dag at substrate.dag:525 has
ONLY { declarations, nodes, ports, clusters }. NO diagnostics
field. Diagnostic-table is PROPOSED substrate extension.

Fix: §2 fail-closed note flagged PROPOSED — Step 2 PR scope
includes `diagnostics: Map<PortId, Diagnostic>` field extension
to Dag, OR PB-Substrate prereq adds it before PB-5 dispatch.

Same recurring feedback_grep_carrier_field_before_coupling_claim
discipline (PR #3126 SurfaceModule analogous case); needed to
grep type Dag fields BEFORE claiming the diagnostics field
exists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3085 INLINE BLOCKING line:94 — §4.1 + §4.3 PROPOSED diagnostic-table marking

Cursor INLINE BLOCKING line:94: §4.1 + §4.3 said "diagnostics
coupled INTO InferredDag" without flagging the diagnostic-table
as a substrate extension. Live Dag at substrate.dag:525 has
{ declarations, nodes, ports, clusters } — NO diagnostics field.
Earlier commit c0d96af added PROPOSED marking only in §2;
§4.1 + §4.3 needed same treatment.

Fix: §4.1 + §4.3 reframed with explicit PROPOSED substrate-
extension marking + reference to §2 for extension scope.
Construction-time invariant + structural coupling are both
contingent on the substrate-extension landing (Step 2 PR scope
or PB-Substrate prereq).

Same recurring feedback_grep_carrier_field_before_coupling_claim
discipline applied to §4.1 + §4.3 consistently with §2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3077 high-level BLOCKING — Practice 4 classifications for PB-4 coproducts

Codex high-level BLOCKING (sha b812db9): "Diagnostic substrate
shape was repaired around anchoring but not re-audited as new
substrate type declarations" — meaning DiagnosticAnchor +
LowerDiagnostic + SurfaceFormRef + IdentifierRef need
🟢/🟡/🔴 classifications per modeling-discipline Practice 4
(Coproduct dissolution).

Same pattern as PB-5 fix in commit 040681f (AlgebraAxis +
InferDiagnostic) applied here.

Fix: added classifications + dissolution triggers:

- SurfaceFormRef 🟢 TERMINAL: closed-axis sum over live Surface*
  carriers; no further dissolution.
- IdentifierRef 🟡 SCAFFOLD: dissolution trigger = Step 2 brief
  enumerates full identifier-kind set against lower.rs
  identifier-resolution sites; promote to 🟢 TERMINAL when
  SurfaceVarRef + TypePathRef + ModulePathRef cover actual axes.
- LowerDiagnostic 🟡 SCAFFOLD: dissolution trigger = Step 2 brief
  enumerates variant set against lower.rs Diagnostic emission
  sites + Q6.5 anti-bridge preserved + PR #3077 §12 Q7
  ratification path.
- DiagnosticAnchor 🟢 TERMINAL: closed-axis covering all
  lowering-stage anchor kinds; no further dissolution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3077 INLINE BLOCKING line:161 — DiagnosticSource Practice 4 classification

Cursor inline finding adds DiagnosticSource to Practice 4
classification scope. Earlier commit aba79a1 classified
SurfaceFormRef + IdentifierRef + LowerDiagnostic + DiagnosticAnchor
but missed DiagnosticSource.

Fix: DiagnosticSource 🟢 TERMINAL at pipeline-stage
discrimination scope. Closed-axis sum (Parse | Lower | Infer |
Emit); adding new pipeline stage requires explicit substrate-
extension audit per Practice 4 + stop-signal discipline (same
shape as PB-5 §3.2 TypeConnective stop-signal).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING line:151 — §11 SurfaceItem::Let + SurfaceLiteral span correction

Cursor INLINE BLOCKING line:151: §11 claimed "every Surface
variant carries SourceSpan" but live parse_surface.dag has:
- SurfaceItem::Let { name, type_ann, expr } — no direct span
- SurfaceLiteral = Int(String) | Bool(Bool) | String(String) —
  plain-tuple variants with no direct span

Source-span provenance for these cases is via enclosing carrier:
SurfaceLiteral wraps within `Literal { value, span }` at
parse_surface.dag:150. Let-item inherits container span.

INVARIANTS P2/P3 source provenance is structurally guaranteed
via direct-OR-enclosing carrier, but my "every variant"
overstatement obscured this.

Fix: §11 corrected to "most Surface variants carry SourceSpan
directly" + explicit Let + SurfaceLiteral exceptions noted +
Step 2 PR scope audits whether exceptions are structural-honest
(enclosing-carrier-provides-span) OR require substrate extension.

Same recurring overstatement class as earlier "every SurfaceItem
maps 1:1 to Declaration" (commit 61e2b67) — need to grep live
substrate variant fields BEFORE claiming uniform shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: gunbc Director

* docs(r3): cursor PR #3126 INLINE BLOCKING line:32 — GrammarSpec is concept, not carrier

Earlier draft (now-merged PR #3126) framed `GrammarSpec` as a second declared
`.dag` input type alongside `List<Token>`. Verified via grep that no
`type GrammarSpec` exists anywhere under src/v3/ or dsl/ — the repo carries
only `parse_tables.dag`'s 6 SG-2c table-families. Per cursor 2026-05-14T23:30:04Z
inline finding, this violates INVARIANTS P2 (the Step-2 signature names a
carrier the substrate doesn't declare).

Reframed §3 (and downstream mentions in §3.2, §3 preamble line:33, §4.2
codex-correction recap line:165, §5.1 line:181, §12 Q6 line:344) so that:

- Parse has ONE input at the API boundary: `List<Token>`.
- "GrammarSpec" is a concept-level grouping for the 6 compile-time table-families
  in `parse_tables.dag`, not a substrate carrier and not a runtime parameter.
- Step-2 signature stays `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>`
  per cfe842b (already applied in #3126); these edits remove the lingering
  "two input types" framing that contradicted that signature.

Per Decision 3.B (b) compile-time parser tables: substrate authority is
parse_tables.dag (6 table-families) consumed via direct table lookups inside
the parser body — no runtime grammar value, no `GrammarSpec` carrier needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3138 BLOCKING — §4.3 + §16 internal contradictions resolved

Codex review id 12391 on sha cd6e8d1 flagged two live statements of the
already-rejected typed-state-with-coupled-diagnostics model still sitting
inside the parse L2.5, contradicting the corrected Result-sum framing in §4.2
and §6 Step 2:

1. §4.3 still proposed a `SurfaceModule { items, diagnostics }` extension
   modeled on PB-4/PB-5 patterns. Reframed: §4.3 now states explicitly that
   parse-stage uses Result-sum (no diagnostics field on SurfaceModule),
   restates the cross-stage discriminator (Result-sum for fail-fast output
   domains: parse + emit; typed-state for structural output domains: lower +
   infer), and cites `parse_generated.rs:138` as the live shape.

2. §16 "Memory disciplines applied" bullet read
   "feedback_state_space_vs_behavioral_invariants (typed-state SurfaceModule
   at output)". Rewritten to "parse output is `Result<SurfaceModule,
   ParseDiagnostic>` — the type rules out partial-parse states by
   construction; SurfaceModule itself carries no diagnostic field per §4.3".

Per `feedback_discipline_change_audit_all_contract_mentions`: when a
contract changes (here: SurfaceModule extension dropped in favor of
Result-sum), all §-internal restatements must be swept in the same diff
or they leak through as authoritative parallel claims.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3127 BLOCKING — drop TokenizedSource extension + cite concrete P5 receipts

Codex review id 12370 on sha d15e1f2 raised two load-bearing planning-shape
findings on the tokenize L2.5. Addressed in this fix-forward branch (PR #3138)
since PR #3127 is still open but accumulating cycles.

Finding 1 — parallel boundary carriers (INVARIANTS P2 / Modeling Practices 3+5):
§4.3 + §9 Step 2 + §12 Q6 named `TokenizedSource { tokens, diagnostics }` as the
output, while §2/§7.2/§7.3 named `List<Token>`. Same misclassification I just
removed from the parse L2.5 in PR #3138 §4.3: tokenize sits in the fail-fast
output domain alongside PB-3 parse + PB-6 emit (a partial token list with a
corrupt token in the middle is not a valid downstream input for parse), so the
failure couples via `Result`, not into the structural carrier.

Resolution:
- §4.3 rewritten to ratify `Result<List<Token>, TokenizeDiagnostic>` — the live
  `tokenize_generated.rs:96` shape — with no `TokenizedSource` extension.
- §9 Step 2 row signature updated to match; explicit "single canonical boundary
  carrier: List<Token> on the Ok branch" framing.
- §12 Q6 resolved REJECTED in-doc (no operator ratification needed; disposition
  follows from the cross-stage discriminator that's also load-bearing in PR
  #3138 parse L2.5).
- §16 memory-disciplines bullets rewritten parallel to PR #3138 parse §16:
  Result-sum, no diagnostics field on `List<Token>`.
- §14 "Surfaces awaiting" trimmed Q6 from the operator-ratification list.

Finding 2 — soft deferral of `regen_tokenize` retirement (INVARIANTS P5):
deferral previously named "PB-Bootstrap-Process lane scope" without a concrete
ROADMAP.md row. Updated §9 Step 2 + Step 4 rows to cite the named receipts:
- `docs/design-pure-bootstrap-zero.md:116` (PB-Bootstrap-Process lane: author
  bootstrap.dag + generated trampoline; sized M).
- `docs/design-pure-bootstrap-zero.md:118-123` (N=0 runtime verification gates).
- ROADMAP.md:467 (Character-level under-consumption in tokenize + syntax
  authorities — phase-2 char-class retype owns the codegen-driver path).
- ROADMAP.md:416 (Class 5 Gap 3 — top-level `ValueBody` boundary; gating
  substrate-capability for the phase-2 retype).
- ROADMAP.md:53 (T-PB-A — non-test census → 0 floor).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 BLOCKING line:119 — §6/§7.2/§15 Q7 sequencing resolved by PR #3077 merge

Cursor inline BLOCKING at docs/design-parse-stage-l25-model.md:119 (sha at
merge time of PR #3126) flagged a real internal contradiction:
- §6 (lines 191, 207, 308) claimed "Step 2 (pipeline-slot declaration) is
  unblocked"
- §7.2 (line 227) claimed "PR #3077 §12 Q7 must ratify before any Step 2
  worker brief authoring"

A worker reading the doc could land Step 2 (pipeline boundary) before the
diagnostic carrier's P2/P3 failure shape was fixed.

Resolution: PR #3077 (PB-4 lower L2.5) merged at 2026-05-15T00:21:19Z,
carrying the §12 Q7 ratification of the Decision 2.B per-stage diagnostic
extension path. The gate IS now satisfied at HEAD, so the resolution is
fact-update (annotate Q7 as DONE with the merge timestamp) rather than
retracting either §6 or §7.2.

Edits:
- §15 step 4: annotated "DONE 2026-05-15T00:21:19Z when PR #3077 merged"
  and added the explicit "Step 2 is now genuinely unblocked, not just
  procedurally next" framing so workers reading the sequence don't bypass
  the gate.
- §7.2 line 227: rewritten from "Q7 must ratify before Step 2 brief
  authoring" (future tense, the contradiction surface) to "Gate satisfied
  2026-05-15T00:21:19Z when PR #3077 merged; Step 2 worker brief authoring
  is unblocked at HEAD per §15 step 4." Cites the cursor finding as the
  resolution path.

§6 unblocking statements stay as-is — they were correct at HEAD; the
contradiction lived in §7.2's pre-merge framing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3126 BLOCKING (sha 16d21f4) — Q7 cited at every Step 2 unblocking claim

Codex BLOCKING finding 2 (sha 16d21f4, 216s thinking): the Q7 dependency
was recorded in §7.2/§15 but not in the other Step-2-unblocking sites at
§6 lines 191, 207, 308 — risking a worker reading "Step 2 unblocked" without
also reading the Q7 prerequisite.

Codex framing: "make Q7 a hard precondition wherever Step 2 is called
unblocked, or split Step 2 into pre-Q7 and post-Q7 scopes with separate
receipts."

Chose the first option since PR #3077 has already merged (2026-05-15T00:21:19Z)
and splitting into pre/post-Q7 scopes is no longer load-bearing. Annotated
all three §6 sites:
- Line 191 (Implication for PB-3 migration): cites gate + merge timestamp
  + explicit "must NOT be brief-authored before that merge timestamp."
- Line 207 (Critical observation): cites the Step 2 gate as PR #3077 §12 Q7
  + merge timestamp + P3 failure-shape consequence if violated.
- Line 308 (Director-recommend phase list): cites gate + §7.2/§15 step 4
  cross-refs + merge timestamp.

Codex BLOCKING finding 1 (GrammarSpec carrier non-existence) verified
already resolved at HEAD via commit c97dc15 — every GrammarSpec mention
now explicitly marks it as a concept-not-carrier; Step 2 signature is
`fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>`
with no GrammarSpec parameter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): openai-pro PR #3126 BLOCKING (sha 16d21f4) — Step 3b/4 atomicity + Q1 ratification-pending status

openai-pro REQUEST_CHANGES on PR #3126 sha 16d21f4 flagged three findings.
Findings 1 + 2 (signature vs realization mismatch under LAYER MODEL + P2/P3
boundary discipline) were already resolved at HEAD by earlier fix-forward
commits — Step 2 signature is now `fn parse(tokens: List<Token>) ->
Result<SurfaceModule, ParseDiagnostic>` matching live `parse_generated.rs:138`
with no GrammarSpec parameter and no diagnostics-coupled SurfaceModule
extension (§4.3 Result-sum disposition).

Finding 6 (TRACKED vs UNTRACKED DEBT — Step 3b/4 same-PR vs two-PR):
§9 had both a "Step 3b/4 COMBINED" row (line 250) and a leftover separate
"Step 4: Parity test" row (line 251) — internally contradictory. §15 also
still sequenced Steps 3b + 4 as four separate authoring/dispatch/ratify
beats (steps 12-17), contradicting §12 Q5's "same PR" decision and the
explicit "Update to §15" note at §12 line 325.

Resolution: collapsed §9 to one COMBINED row absorbing the parity-TestClaim
mechanics + P5 dissolution receipt from the deleted Step 4 row; collapsed
§15 steps 12-17 into single COMBINED authoring + dispatch + ratify (steps
12-14). Added explicit `feedback_paper_shrink_variants` reasoning in both
sections.

Finding 2.5 (PM intent — substrate-capability bundled vs separate):
§12 Q1 line 288 said "Director-recommend: (b) bundled" while §13 line 340
listed substrate-capability as a non-goal of PB-3 and §15 step 11 had
"WAIT for substrate-capability landing" — three sections, two different
execution paths.

Resolution: annotated Q1 as "PENDING operator/PM ratification" with
explicit default-execution clause: until operator ratifies, the doc
treats substrate-capability as path (a) separate lane (matching §13 + §15
+ §9 row). If/when ratified to (b), §13 drops the non-goal and §15 step 11
collapses into the COMBINED Step 3b/4 brief.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3126 BLOCKING (sha 5619afa) — parse_tables.dag as single enumerated authority

Codex caught me copying the prose summary at parse_tables.dag:23-29 (which
enumerates only SG-2c-numbered families) instead of grepping the live
`^type [A-Z]` declarations. Result: SoftKeywordIdentRow (line 334) was
missing from §3.2 / §5.1 / §6 / §12 because it lacks an SG-2c-N number
in the prose summary.

Per `feedback_parallel_representation_debt`: structural fix is to stop
hand-enumerating in the doc — cite parse_tables.dag itself as the single
enumerated authority and use `type`-declaration line-anchors for the
worked example, not a hand-maintained count.

Edits:
- §3.2 §"Live substrate authority": replaced the SG-2c-numbered bullet
  list with `type`-declaration line-anchor enumeration including
  SoftKeywordIdentRow at parse_tables.dag:334 + the supporting enum
  BinaryOpLevel at line 133. Added codex-finding callout explaining the
  miss + the discipline shift.
- §3 preamble line:33, §3.2 line:45 callout, §3.2 line:57 framing,
  §3.2 §"Substrate authority" line:71, §5.1 line:171-180, §12 Q2 line:298,
  §12 Q6 line:334: all hardcoded "6 table-families" counts dropped; doc
  now points readers to §3.2 enumeration / `parse_tables.dag` directly.
- §5.1 sub-enumeration list (the parallel 6-item list at lines 173-178)
  deleted; replaced with redirect to §3.2 + restated 3a-vs-3b/4 scope split.

Code-level check before commit: `grep -nE '^type [A-Z]' src/v3/compiler/parse_tables.dag`
returns 7 types: BinaryOpLevel (133), BinaryOpRow (167), TopLevelItemKwRow (289),
SoftKeywordIdentRow (334), BracketRow (385), PrimaryPrefixRow (449),
PrimaryAtomRow (486). Doc enumeration matches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3138 BLOCKING (sha f08b952) — bind TokenizeDiagnostic to live CharClass authority

Codex Finding 1 (sha f08b952, 216s thinking): the §4.2 TokenizeDiagnostic
draft and the §5.1/§5.2 headings used `ScannerCharClass` / `ScannerClassRef`
— names that exist only as the *generated Rust enum spelling*, not as a
declared .dag substrate type. Verified via grep:

  grep -rn '^type CharClass\|^type ScannerC' dsl/ src/v3/

returns ONE authority: `dsl/std/unicode.dag:62`
  type CharClass = Whitespace | Digit | IdentStart | IdentContinue

consumed at `src/v3/compiler/tokenize.dag:103`
  data ascii_scan_order: List<CharClass> = [Whitespace, Digit, IdentStart, IdentContinue]

There is no `ScannerCharClass` declaration anywhere — that name was copied
from generated Rust without grep-verification, the same failure mode as
`feedback_grep_substrate_before_naming_ratification` (carrier-name
collision discipline).

Resolution:
- §4.2 TokenizeDiagnostic carrier: `expected_class: ScannerClassRef` →
  `expected_class: CharClass`, dropped the `type ScannerClassRef =
  ScannerCharClass` alias entirely; added a codex-finding callout citing
  the substrate authority + naming the failure mode.
- §5.1 heading "Byte → ScannerCharClass dispatch" → "Byte → CharClass
  dispatch"; bullets unchanged; added line-anchor cites for the substrate
  authority + explicit "NOT ScannerCharClass" disclaimer.
- §5.2 heading "ScannerCharClass → token-recognition state machine" →
  "CharClass → token-recognition state machine".

Finding 2 (TokenizedSource not reconciled with parse input contract): no
new fix required — already resolved by commit 6adb992 (TokenizedSource
extension dropped entirely; tokenize uses Result<List<Token>,
TokenizeDiagnostic>; List<Token> is the single canonical boundary carrier
consumed by parse). Codex was reviewing sha f08b952, which predated the
TokenizedSource drop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3138 INLINE BLOCKING line:188 — clarify §7.3 chain is Ok-branch propagation

Cursor INLINE at sha f08b952 worried that §7.3's cross-stage chain
"tokenize → List<Token> → parse → ..." was inconsistent with §4.3's
TokenizedSource carrier (diagnostics not flowing forward). At HEAD the
TokenizedSource extension is dropped (commit 6adb992); tokenize uses
Result<List<Token>, TokenizeDiagnostic>, so List<Token> IS the canonical
Ok-branch payload that flows forward and Err branches terminate the
pipeline fail-fast.

To make this explicit at §7.3 (instead of leaving readers to infer it
from §4.3), annotated the chain with:
- "Ok-branch propagation; Err branches are stage-terminal fail-fast per
  §4.3 Result-sum discriminator" framing prefix.
- Per-stage Result/typed-state annotations: tokenize/parse show
  Result<Ok, Err>; lower/infer show typed-state structural-output;
  emit shows Result<EmittedArtifact, EmissionDiagnostic>.
- Explicit "on any stage's Err branch the pipeline aborts at that stage
  (no partial-output propagation across boundaries)" trailer.

This makes the chain self-consistent vis-a-vis §4.3 without requiring
the reader to walk back-and-forth, and prevents future readers from
re-introducing a TokenizedSource-shaped extension to "make diagnostics
flow forward" — they already do, just via the Err branch terminating
the pipeline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): openai-pro PR #3127 BLOCKING (sha d15e1f2) — character-level scaffold dissolution trigger

openai-pro REQUEST_CHANGES on sha d15e1f2: §1 line:26 character-level
under-consumption scaffold named the problem but lacked a checkable
dissolution trigger. SG-1a scaffold above had the right shape — "once
those bodies lower structurally under compile_to_dag, delete the raw-text
extractor + derive directly from lowered Dag in same PR." Character-level
scaffold just said "PB-2 Step 4 carries this scope" — a lane assignment,
not a trigger.

Resolution: rewrote §1 item 2 with the same SG-1a-shape trigger structure:
- Substrate-consumption condition (a): scanner classes / string escape /
  local punctuation retype to `dsl/std/unicode.dag` `CharClass` /
  `char_in_class` (concrete field retypes named:
  `StringEscapeSpec.suffix: Char`, `LocalPunctSpec.pattern: List<Char>`,
  `string_literal_delimiter: Char`).
- Codegen-driver condition (b): `tokenize_generated.rs` no longer emits
  hidden `byte.is_ascii_*` predicates because the driver reads class
  facts structurally from lowered `tokenize.dag`.
- Same-PR dissolution: delete the parallel character-predicate scaffold
  in the same PR that flips substrate consumption — no Rust-and-`.dag`
  coexistence per `feedback_paper_shrink_variants`.
- Cross-ref to §9 Step 4 gating prereqs: ROADMAP.md:467 + ROADMAP.md:416
  Class 5 Gap 3 + std.unicode bootstrap/load-set decision (already cited
  in §9 from earlier commit 6adb992).

Per openai-pro's framing: "small fix — mirror the SG-1a scaffold wording
by naming the exact substrate-consumption condition and same-PR deletion
receipt for the hidden Rust character predicates."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: gunbc Director

* docs(r3): cursor PR #3127 APPROVE_WITH_COMMENTS — §14 + §15 Q6-already-rejected sweep

Cursor review id 12405 (APPROVE_WITH_COMMENTS) caught the same
`feedback_discipline_change_audit_all_contract_mentions` failure mode
recurring: §12 Q6 was resolved REJECTED in commit 6adb992, and §14
"Surfaces awaiting" + §12 Q6 heading + §9 Step 2 row were updated, but
two §-internal contract restatements were missed:

- §14 acceptance criterion 11: "Operator/PM ratification on §12 Q1-Q6"
- §15 step 1: "Operator / PM-delegate ratifies §12 Q1-Q6"

Both contradicted §12 Q6 + §14 "Surfaces awaiting" (which already said
"Q1-Q5 only"). A worker reading §14/§15 could schedule sign-offs on Q6
after it was already resolved-rejected elsewhere.

Resolution: both sites now say "Q1–Q5" with the explicit Q6-rejected
crossref + "see §14/§15 for same scoping" pointer at the §14 criterion
so the three sections agree internally.

Cursor verdict was APPROVE_WITH_COMMENTS (substantive APPROVE — "fix the
checklist/sequence so every section agrees Q6 is closed"); the
exploratory volatile-line-anchor note is harmless and out-of-scope for
this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3138 BLOCKING (sha 887c696) — 3 findings swept across 3 L2.5 docs

Codex review id (sha 887c696, 333s thinking) flagged three findings,
all `feedback_discipline_change_audit_all_contract_mentions` recurrences
where partial sweeps left §-internal contradictions.

Finding 1 — infer doc cross-stage trigger leak:
§4.2 InferDiagnostic dissolution trigger said "when Step 2 worker brief
enumerates the full variant set against `parse_generated.rs`
Diagnostic::ParseError, lower.rs Diagnostic construction sites, and
infer.rs Dag::mark_unresolved emission sites." That cross-stage trigger
surface is wrong for the infer-specific scaffold. Narrowed to infer-only:
"against `src/v3/compiler/src/infer.rs` Diagnostic construction sites +
`Dag::mark_unresolved` emission sites (infer-stage only)." Parse and lower
have their own per-stage carriers + own Q7 mapping; this doc no longer
reaches into their dissolution-trigger surface.

Finding 2 — parse + tokenize coproduct receipts:
`ParseDiagnosticKind` (parse §4.2) and `TokenizeDiagnostic` (tokenize §4.2)
sums were declared without the 🟡 SCAFFOLD / 🟢 TERMINAL classification +
dissolution trigger that the infer doc carries (per modeling-discipline
Practice 4 + `feedback_coproduct_dissolution`). Added matching scaffold
receipts to both: 🟡 SCAFFOLD at PROPOSED stage with stage-local dissolution
trigger (Step 2 brief enumerates against parse_generated.rs / tokenize_generated.rs
Diagnostic::* construction sites — stage-only, not cross-stage); promote
to 🟢 TERMINAL when full variant set lands. Both also carry the anti-bridge
note per Q6.5.

Finding 3 — tokenize Q7 reconciliation:
The parse doc has the "Q7 DONE 2026-05-15T00:21:19Z" annotation at §15 step 4
(commit f85fa1f) but the tokenize doc still framed Q7 as a pending lane
dependency at §4.2 line:113 ("Lane dependency"), §15 step 3, and §14
"Surfaces awaiting". Annotated all three:
- §4.2 "Lane dependency": Q7 DONE timestamp + "TokenizeDiagnostic per-stage
  variant authoring is the remaining lane work."
- §15 step 3: full DONE annotation matching parse doc §15 step 4 shape +
  cross-ref to the parse doc.
- §14 "Surfaces awaiting": strikethrough + DONE annotation.

PR #3127 also carries the tokenize doc; same edits will port there in a
companion commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3138 INLINE BLOCKING line:372 — §16 Surfaces awaiting Q7 contradiction

Cursor inline at sha 887c696 caught the symmetric finding to the codex
5-finding BLOCKING #3: parse-doc §15 step 4 already annotated Q7 as DONE
(commit f85fa1f) but parse-doc §16 "Surfaces awaiting" still listed Q7
as pending. Same `feedback_discipline_change_audit_all_contract_mentions`
sweep failure — the tokenize doc had three sites carrying the pending
framing (commit e9739ea fixed those) but the parse doc's §16 site was
missed in the original Q7-DONE sweep.

Resolution: §16 bullet now strikes through + "DONE 2026-05-15T00:21:19Z
(PR #3077 merged carrying Q7 ratification; see §15 step 4)" — same shape
as the tokenize doc's §14 "Surfaces awaiting" Q7-DONE annotation landed
in e9739ea.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request May 15, 2026
…+ cursor inlines (#3141)

* docs(r3): PB-2 tokenize pipeline-stage L2.5 domain model — DRAFT for ratification

Director-tier L2.5 model for PB-2 tokenize per operator 2026-05-14
ratification (Decision 1.A scoping = Option A).

PB-2 is the FURTHEST-ALONG pipeline stage — substrate authority
already lives in `.dag`:
- src/v3/std/tokenize.dag (Token + TokenKind taxonomy; LIVE 143
  lines)
- src/v3/compiler/tokenize.dag (tokenizer implementation; LIVE
  154 lines)
- src/v3/compiler/src/tokenize_generated.rs (AUTO-GENERATED; 362
  lines)

This is the END STATE that all other pipeline-stage migrations
target. PB-2 L2.5 is correspondingly lighter — mostly verification
+ residual hand-Rust retirement, NOT new substrate authoring.

Distinct §9 4-step framing:
- Step 3 = VERIFY substrate completeness (audit per
  feedback_paper_shrink_variants)
- Step 4 = HANDOFF/RETIRE residual hand-Rust scaffolding
  (coordinates with PB-Bootstrap-Process lane for codegen-driver
  retirement)

Captures audit dimensions explicitly:
- scanner-class definitions = declarative byte-pattern membership
- recognition tables = closed-axis enums
- state machine = structural transitions
- no V2 `pub mod tokenize` absorption check

§12 Q1: codegen-driver retirement scope — Director-recommend
PB-Bootstrap-Process handles all codegen-driver retirement
cross-cuttingly (not per-stage paper-shrink risk).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): §12.6 citation fix — tokenize is PB-2 lane scope per design-pure-bootstrap-zero.md

Per cursor PR #3085 finding: §12.6 explicitly tables only 4
pipeline-stage migrations (emit→lower→infer→parse); tokenize is
per design-pure-bootstrap-zero.md PB-2 lane. Same fix as PR #3085
commit 89fbd7a2a applied here.

INVARIANTS P1 — documentation must not overstate authority cites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): preemptive fix for PR #3126 codex BLOCKING propagation — PB-2 live state honesty

Same class as codex INLINE BLOCKING #3126 finding 1 (live state
honesty for diagnostic coupling) applied preemptively to PB-2
tokenize L2.5.

PB-2 §4.3 had "diagnostics coupled INTO List<Token>" framing
which would overstate the live carrier shape (bare List<Token>
has no diagnostic field; tokenize_generated.rs:96 today returns
Result<Vec<Token>, Diagnostic>).

Fix: §4.3 reframed with PROPOSED substrate extension explicit —
new `TokenizedSource { tokens, diagnostics }` wrapper carrier as
the typed-state output. Step 2 brief includes wrapper authoring
in pipeline-slot PR scope.

Same discipline as PR #3126 commit bdff8c500.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3077 — fix PB-2 lane citation (design-pure-bootstrap.md not -zero.md)

Per cursor APPROVE_WITH_COMMENTS /api/reviews/12087: PB-2 lane is
defined in docs/design-pure-bootstrap.md §"PB-2 — tokenize retire"
(line ~134), NOT docs/design-pure-bootstrap-zero.md. The -zero.md
doc has Subsumed-lanes list with PB-1/PB-4/PB-5/PB-6 but NOT PB-2.

Propagated fix applies same cite-error correction as PR #3066 §1.8
discipline: cite the actual doc, not an adjacent doc with similar
name. INVARIANTS P2 single-authority-citation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): fix cursor PR #3127 BLOCKING contradictions + add §12 Q6

Cursor APPROVE_WITH_COMMENTS (/api/reviews/12093) caught two
substantive contradictions I introduced when adding TokenizedSource
in commit 2b9756bb5:

1. §4.3 vs §9 Step 2 signature mismatch — §4.3 said `-> TokenizedSource`
   but §9 Step 2 row still said `-> List<Token>`. Same
   `feedback_discipline_change_audit_all_contract_mentions` issue
   that's recurred 4x this session.

2. §4.3 referenced "§12 Q-new" but §12 only had Q1-Q5; broken anchor.

Fix:
1. §9 Step 2 row updated: signature `-> TokenizedSource` with
   wrapper carrier shape `{ tokens, diagnostics }` per §4.3
2. §4.3 anchor updated: "§12 Q6" (resolved)
3. Added §12 Q6: TokenizedSource carrier shape ratification —
   (a) wrapper record vs (b) per-Token diagnostic coupling;
   Director-recommend (a) for PB-3 SurfaceModule parallelism
4. §14 + §15 + §16 Q-list refs updated to Q1-Q6

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): fix codex BLOCKING PR #3127 — Token shape + Q4 audit boundary

Codex REQUEST_CHANGES (sha b881de23) with 2 substantive findings:

1. §4.1 Token shape claim "optional lexeme: String" — wrong per
   live substrate at src/v3/std/tokenize.dag:65-67. Live Token
   has 2 fields only (kind + span); lexeme-content lives ON the
   TokenKind variants (Ident(String) / IntLit(String) / etc.).

   Fix: corrected §4.1 to reflect live carrier shape; payloads
   on TokenKind variants noted explicitly.

2. §12 Q4 substrate-completeness audit scoped only to
   tokenize_generated.rs — missed the regen_tokenize codegen-
   driver boundary. If regen_tokenize carries scanner-logic
   decisions (rather than mechanical template-rendering of
   substrate facts), the substrate isn't complete — the driver
   IS hand-Rust scanner logic in disguise.

   Fix: Q4 audit extended with (d) regen_tokenize codegen-
   driver logic audit + (e) ROADMAP.md deferral row option per
   feedback_paper_shrink_variants P5 receipt discipline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): fix codex BLOCKING PR #3127 — TokenizeDiagnostic PROPOSED + scaffold disclosure

Codex REQUEST_CHANGES (sha b881de23, full body) caught 2 substantive
overstatements:

1. §2 line 46 claimed "tokenize failures produce typed
   TokenizeDiagnostic variants" — but live tokenize_generated.rs:96
   returns generic `Result<Vec<Token>, Diagnostic>` with
   `Diagnostic::TokenizerError { message, span, correction }`. Typed
   TokenizeDiagnostic is a PROPOSED extension, not live state.

   Fix: §2 reframed with live state explicit + TokenizeDiagnostic
   marked PROPOSED per PR #3077 §12 Q7 ratification path.

2. §1 line 22 + §6 + §9 Step 2 line 198 framed PB-2 as "mostly
   verification" — but live tokenize.dag:16-30+ has TWO explicit
   tracked scaffold zones:
   - SG-1a: regen_tokenize parses raw source text for
     dag_keyword_set / dag_operators (ValueBody::Unparsed)
   - Character-level under-consumption: StringEscapeSpec /
     LocalPunctSpec.pattern / string_literal_delimiter as opaque
     Strings; hidden Rust character predicates (byte.is_ascii_digit
     etc.) at tokenize_generated.rs:15-22 leaking through codegen

   Residual hand-Rust is NOT just the codegen artifact — it includes
   (a) regen_tokenize logic, (b) SG-1a raw-text-extractor scaffold,
   (c) character-predicate scaffold leaking through codegen.

   Fix: §1 + §6 + §9 Step 2 reframed honestly. PB-2 is "FURTHER
   ALONG but not complete"; Step 4 carries scaffold-retirement
   scope, not just codegen-artifact retirement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): post-merge fix-forward — §16 + §9 Step 2 internal contradictions

Two post-merge doc-internal contradictions caught by reviewers
after operator merged PR #3077 / #3126 / #3085 at 2026-05-15T00:21Z.

**PR #3077 PB-4 lower §16 fix**:
§16 "Memory disciplines applied" bullet said "diagnostics coupled
INTO PreInferDag via biconditional" — but §4.3 (per openai-pro
DiagnosticAnchor fix commit b812db91b) constrains biconditional
to PortAnchor-only. Other anchor kinds (DeclarationAnchor /
RecordFieldAnchor / SurfaceFormAnchor) couple without port-state.
Fix: §16 bullet honors §4.3 anchor-typed framing.

**PR #3126 PB-3 parse §9 Step 2 fix**:
§9 Step 2 row described diagnostics as "coupled INTO SurfaceModule"
as if live — §4.3 correctly marks it PROPOSED. Same
feedback_discipline_change_audit_all_contract_mentions pattern
that's recurred this session.
Fix: §9 Step 2 row clarified — "PROPOSED extension per §4.3";
Step 2 PR scope includes authoring the diagnostics field
extension, NOT a live coupling.

Per feedback_discipline_change_audit_all_contract_mentions: when
a substantive fix changes a discipline framing, audit ALL sections
(framing + contract + handoff). Post-merge audit surfaced these
residual contradictions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): post-merge fix-forward — PR #3126 codex BLOCKING (GrammarSpec parallel-authority + fail-closed weakening)

Codex REQUEST_CHANGES on already-merged PR #3126 (/api/reviews/12175):
2 substantive findings on the post-merge doc.

**Finding 1 (P2 violation — GrammarSpec parallel authority)**:

§3.2 says GrammarSpec is compile-time-only, NOT runtime-
interpreted (per Decision 3.B (b) operator override). But the
proposed stage contract still took `grammar: GrammarSpec` as
runtime input. Creates two authorities (compiled parser tables
+ runtime GrammarSpec value).

Fix: §4.3 signature reframed to `fn parse(tokens: List<Token>)
-> Result<SurfaceModule, ParseDiagnostic>` — NO runtime
GrammarSpec input. Compile-time generated parser tables consumed
via internal dispatch. Step 2 + Step 4 rows updated.

**Finding 2 (P3 + Practices 1/2 — fail-closed weakening)**:

Live parser at parse_generated.rs:138 returns `Result<SurfaceModule,
Diagnostic>` (fail-closed; aborts on first error). Earlier draft
proposed `SurfaceModule` with embedded diagnostics — would let
partial-parse states be constructible + let downstream observe
"success" output after parse failure. Violation of fail-closed
discipline.

Fix: signature preserves Result-sum (matches live + emit's
pattern). Distinguished cross-stage:
- Result-sum (parse + emit): fail-fast output domain
- Typed-state-with-coupled-diagnostics (lower + infer): structural
  output domain where partial-failure IS valid intermediate

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 post-merge APPROVE_WITH_COMMENTS — §4.1 + §16 fail-closed honesty

Cursor caught 2 more post-merge contradictions on PR #3126:

1. §4.1 line 81 "construction-time invariant" talks about
   "ParseDiagnostic in the diagnostic stream" tied to SurfaceModule
   path — but §5.2 + live parse_generated.rs:138 use
   Result<SurfaceModule, Diagnostic>. §4.1 reads as claim about
   today's plumbing.

   Fix: §4.1 reframed — live boundary explicit (Result-sum);
   construction-time invariant scoped to Ok-arm SurfaceModule +
   Err-arm ParseDiagnostic, no partial-parse with embedded
   diagnostics.

2. §16 line 397 cites C-8 as "ParseDiagnostic coupled INTO
   SurfaceModule" without qualifier — but §4.3 (post codex
   REQUEST_CHANGES fix) constrains to Result-sum.

   Fix: §16 bullet honors §4.3 Result-sum framing; cross-stage
   discriminator named.

Same recurring feedback_discipline_change_audit_all_contract_mentions
pattern — substantive fix to §4.3 + §9 Step 2 left §4.1 + §16
inconsistent. Post-merge audit catches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3085 INLINE BLOCKING — TypeConnective extension stop-signal

Cursor INLINE BLOCKING caught §3.2 line 66 "rules extend
automatically" weakens substrate-extension stop-signal. Thesis
discipline: a 7th TypeConnective variant requires explicit C1
audit + named infer-rule receipt.

Fix: §3.2 reframed. New TypeConnective variants do NOT extend
automatically; require explicit C1 substrate-extension audit +
named infer-rule receipt for the new variant's structural
inference behavior.

Per-variant structural facts means new variants need new
per-variant facts, NOT silent inheritance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3085 INLINE BLOCKING — AlgebraAxis + InferDiagnostic Practice 4 classification

Cursor INLINE BLOCKING /api/reviews/12218 (line:112): proposed
substrate coproducts (AlgebraAxis + InferDiagnostic) lack
🟢/🟡/🔴 classification + ledger/trigger per modeling-discipline
Practice 4 (Coproduct dissolution).

Fix: added 🟡 SCAFFOLD classification + named dissolution
trigger for both:

AlgebraAxis 🟡 SCAFFOLD:
- Trigger: Step 2 brief enumerates full algebra-axiom set
  against infer.rs check sites + verifies coverage parity
  with live verification.dag:146 AlgebraicLawKind 3-variant
  subset → promote to 🟢 TERMINAL.

InferDiagnostic 🟡 SCAFFOLD:
- Trigger: Step 2 brief enumerates full variant set against
  parse_generated.rs / lower.rs / infer.rs diagnostic emission
  sites → promote to 🟢 TERMINAL.
- Anti-bridge per Q6.5: does NOT collapse into
  CompilerDiagnosticKind without substrate-extension
  ratification per PR #3077 §12 Q7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3077 INLINE BLOCKING — §5.1 SurfaceItem allocation correction

Cursor INLINE BLOCKING /api/reviews/12251 line:130: §5.1 said
"every SurfaceItem variant maps 1:1 to a Declaration placeholder"
but live lower.rs:2950-2958 explicitly skips Let/Module/Import
in collect_symbols.

Verified via Read of lower.rs:2956-2958:
  SurfaceItem::Let { .. } => continue,
  SurfaceItem::Module { .. } => continue,
  SurfaceItem::Import { .. } => continue,

Fix: §5.1 reframed — DeclarationAllocating variants (Fn /
FnExternalBody / Data / TypeAtom / TypeRecord) map to
placeholders; NonDeclarationAllocating variants (Let / Module /
Import) skip allocation per live lower.rs behavior.

Let-bodies lower to Bind expressions in Pass 2; Module/Import
are parsed-facts preserved but un-declared.

Earlier "every SurfaceItem variant" framing overstated; would
have steered Step 2/3 worker into wrong allocation contract.
Per INVARIANTS P1/P2 live-state honesty + facts-flow-forward.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3077 INLINE BLOCKING — ElaborationSpec scope broadened

Cursor INLINE BLOCKING line:33: ElaborationSpec was defined only
as Surface→Behavior recipe mapping, but lower constructs
Declarations / TypeConnectives / BranchPatterns / Bindings as
well. Non-Behavior lowering decisions outside declared authority
violates THESIS substrate ownership + INVARIANTS P2.

Fix: §3.2 ElaborationSpec scope broadened to ALL lowering
decisions:

1. SurfaceItem → Declaration recipes (Fn / Data / Type variants +
   Let/Module/Import skip-allocation per §5.1)
2. SurfaceType → TypeConnective recipes (Atom / Arrow / Compose /
   Disj construction)
3. SurfaceExpr → Behavior recipes (Value / Transform / Branch /
   Loop / Bind construction)
4. SurfacePattern → BranchPattern recipes (ResolvedVariant /
   UnresolvedVariant / record-pattern construction)
5. Binding-site rules (Bind params + result_port construction)

ElaborationSpec is single-authority across ALL axes; no axis
lives in implementation-tier hand-Rust.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — §7.1 ordering vs independence clarification

Cursor APPROVE_WITH_COMMENTS /api/reviews/12265 line 197: §7.1
mixed two claims:
- "parse migrates AFTER tokenize substrate-side stable" (ordering)
- "PB-3 parse migration is independent of PB-2 tokenize migration
  status" (independence)

Read as contradictory by reviewers. Need one coherent story.

Fix: §7.1 reframed with two distinct axes explicit:

1. Substrate-stability ordering (SELF_HOSTING.md §2 bottom-up):
   tokenize Token carrier shape must be stable BEFORE parse
   migrates. Already true at HEAD (tokenize.dag:65-67 declares
   live carrier). ✓

2. Migration-timing independence (parallel-dispatch axis): PB-3
   parse migration ships in parallel with PB-2 residual-retirement
   work (SG-1a + character-level scaffold + codegen-driver
   retirement per PB-2 L2.5 §1). What parse needs is the stable
   Token CARRIER; PB-2's migration is about retiring residual
   hand-Rust, not changing the carrier.

Both claims coherent on the axis split; not contradictory.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING — ParseDiagnostic SourceSpan structural requirement

Cursor INLINE BLOCKING /api/reviews/12277 line:65: ParseDiagnostic
variants like UnexpectedToken lacked SourceSpan field;
List<ParseDiagnostic> cannot satisfy fail-closed source
attribution structurally without span on every variant.
INVARIANTS P2/P3 violation.

Fix: every ParseDiagnostic variant now carries SourceSpan
structurally:
- UnexpectedToken: added span: SourceSpan
- UnterminatedConstruct: opener_span: SourceSpan (already present)
- InvalidLiteral: added span: SourceSpan
- DuplicateRecordFieldLabel: added span: SourceSpan (current site)
  + prior_span: SourceSpan (prior site; both required)

Per INVARIANTS P2/P3 fail-closed source attribution discipline:
every diagnostic emission carries structural source-span
provenance; not optional.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING — Token authority cite phantom-reference fix

Cursor INLINE BLOCKING /api/reviews/12279 line:29: §3.1 cited
`src/v3/compiler/src/tokenize.rs` as "current hand-Rust" for
Token carrier — but `tokenize.rs` (without _generated suffix)
doesn't exist. Live state has tokenize.dag (live substrate) +
tokenize_generated.rs (codegen artifact).

Per design-pure-bootstrap.md PB-2 lane: tokenize retire has
substantially landed. The reference was an earlier-draft
phantom from when Token-was-hand-Rust framing was the assumption.

Fix: §3.1 reframed — Token type lives in LIVE
src/v3/std/tokenize.dag:65-67 shared taxonomy; tokenizer
implementation also live at src/v3/compiler/tokenize.dag (154
lines); codegen artifact at tokenize_generated.rs. tokenize.rs
phantom reference removed explicitly. PB-2 substantially landed
per design-pure-bootstrap.md; residual scaffold-retirement
scope per PB-2 L2.5 PR #3127.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING — Step 2 pipeline-slot target fix (compiler.dag → pipeline.dag)

Cursor INLINE BLOCKING /api/reviews/12281 line:138: §9 Step 2
referenced generic "compiler.dag" but dsl/gunbc/compiler.dag:24
explicitly directs internal pipeline (Tokenize → Parse → ...)
to src/v3/compiler/pipeline.dag, NOT generic compiler.dag.

Worker briefs authored against this doc would target the wrong
file for pipeline-slot declaration. P2 single-authority violation.

Fix: §9 Step 2 row in ALL 4 L2.5 docs (PB-2 / PB-3 / PB-4 / PB-5)
updated:
- "declared in compiler.dag" → "declared in src/v3/compiler/pipeline.dag (per dsl/gunbc/compiler.dag:24 — internal pipeline lives in pipeline.dag, NOT generic compiler.dag)"
- substrate column: "compiler.dag refinement" → "pipeline.dag refinement"
- §13 "Step 2 (pipeline-slot in compiler.dag)" → "pipeline-slot in src/v3/compiler/pipeline.dag"

Same phantom-citation class as the tokenize.rs phantom (commit
8ae37b4a5): I cited generic file path without verifying which
specific file is authoritative per project structure. Should
have grep'd dsl/gunbc/compiler.dag header notes before authoring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING — Step 3b/4 phasing P5 receipt unambiguity

Cursor INLINE BLOCKING /api/reviews/12283 line:181: Q5 said
Step 3b "full parser body .dag migration + parser body deletion
in same PR", but §15 sequence schedules Step 4 parity/deletion
AFTER Step 3b merges. P5 dissolution receipt ambiguous.

If Step 3b lands .dag parser body BEFORE Step 4 deletes Rust
parse() body, Rust + .dag parser bodies coexist temporarily —
paper-shrink-relocation risk per feedback_paper_shrink_variants.

Fix:
1. §9 Step 3b row reframed as "Step 3b/4 COMBINED" — atomic
   single PR (full .dag parser body + parity TestClaim +
   parse_generated.rs:138 deletion + census shrink). Cannot land
   .dag parser body before Rust deletion.
2. §12 Q5 phasing clarified:
   - Phase 3a (separate PR): grammar table extension; P5 receipt
     = ROADMAP deferral row naming Step 3b/4 as future-receipt
   - Phase 3b/4 COMBINED (single PR): atomic substrate substitution
3. §9 + §15 update notes: sequence collapses steps 12-17 into
   single dispatch+merge for combined phase

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3126 high-level BLOCKING findings 1 + 2

Codex high-level BLOCKING (sha 140eb6bb) had 4 findings:
- Findings 3 + 4 already addressed in PR #3138 commits 015977347
  + a1607a88d
- Findings 1 + 2 addressed in this commit

**Finding 1 (Diagnostic kind/record conflated)**:
§4.2 ParseDiagnostic was modeled as variants-directly with span
+ kind-fields mixed. Live Diagnostic at diagnostics.dag:150 uses
record-wraps-kind pattern (`{ kind, span, message, correction }`).
Need consistent shape.

Fix: refactored to record-wraps-kind:
- `type ParseDiagnostic { kind: ParseDiagnosticKind, span: SourceSpan }`
- `type ParseDiagnosticKind = UnexpectedToken | UnterminatedConstruct | InvalidLiteral | DuplicateRecordFieldLabel | ...`

Span lives on ParseDiagnostic record (single source of truth);
variant-specific spans (opener_span / prior_span) remain on kind
variants where meaningful.

**Finding 2 (PB-2 §6 obsolete sibling-lane assumption)**:
§6 line 198 said "PB-2 Tokenize | src/v3/std/tokenize.dag (NEW
per PB-2 L2.5)" — but tokenize.dag is ALREADY LIVE per
design-pure-bootstrap.md §"PB-2 — tokenize retire" (substantially
landed).

Fix: §6 prereq table row updated to reflect LIVE state. PB-2's
residual scope is scaffold-retirement (SG-1a + character-level +
codegen-driver per PB-2 L2.5 §1), not carrier authoring. PB-3
consumes the live Token carrier; carrier shape stable across
PB-2 residual-retirement timing.

Findings 3 + 4 already addressed:
- Finding 3 (pipeline.dag target): commit 015977347
- Finding 4 (Step 3b/4 atomic vs sequential): commit a1607a88d

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 APPROVE_WITH_COMMENTS — phantom "module-level metadata" removed

Cursor APPROVE_WITH_COMMENTS line:79: §4.1 said "SurfaceModule
(verified live) carries List<SurfaceItem> + module-level
metadata" — but live parse_surface.dag:29 has ONLY
`{ items: List<SurfaceItem> }`. No metadata fields.

Phantom addition violated INVARIANTS P1 live-state honesty.

Fix: §4.1 reframed to match live carrier exactly. Same
phantom-addition class as tokenize.rs phantom (commit 8ae37b4a5).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3085 high-level BLOCKING findings — AtomPayload 5-variant + diagnostic-table PROPOSED

Codex high-level BLOCKING (sha bf4d3152) — 2 substantive findings:

**Finding 1 (AtomPayload stale)**:
§2 + §5 cited infer.rs:10 top-comment "Atom(Identifier { name,
resolved })" — but live substrate.dag:87 has 5-variant
AtomPayload sum: Literal | UnresolvedIdentifier |
ResolvedByStructure | ResolvedByName | TypeParam.

infer.rs top-comment is STALE vs live substrate. My doc inherited
the drift.

Fix: §2 enumeration corrected to all 5 AtomPayload variants per
live substrate.dag:87.

**Finding 2 (diagnostic-table PROPOSED, not live)**:
§2 + §4.1 + §4.3 said "diagnostics.contains(port_id)
biconditional" as if live — but Dag at substrate.dag:525 has
ONLY { declarations, nodes, ports, clusters }. NO diagnostics
field. Diagnostic-table is PROPOSED substrate extension.

Fix: §2 fail-closed note flagged PROPOSED — Step 2 PR scope
includes `diagnostics: Map<PortId, Diagnostic>` field extension
to Dag, OR PB-Substrate prereq adds it before PB-5 dispatch.

Same recurring feedback_grep_carrier_field_before_coupling_claim
discipline (PR #3126 SurfaceModule analogous case); needed to
grep type Dag fields BEFORE claiming the diagnostics field
exists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3085 INLINE BLOCKING line:94 — §4.1 + §4.3 PROPOSED diagnostic-table marking

Cursor INLINE BLOCKING line:94: §4.1 + §4.3 said "diagnostics
coupled INTO InferredDag" without flagging the diagnostic-table
as a substrate extension. Live Dag at substrate.dag:525 has
{ declarations, nodes, ports, clusters } — NO diagnostics field.
Earlier commit c0d96af25 added PROPOSED marking only in §2;
§4.1 + §4.3 needed same treatment.

Fix: §4.1 + §4.3 reframed with explicit PROPOSED substrate-
extension marking + reference to §2 for extension scope.
Construction-time invariant + structural coupling are both
contingent on the substrate-extension landing (Step 2 PR scope
or PB-Substrate prereq).

Same recurring feedback_grep_carrier_field_before_coupling_claim
discipline applied to §4.1 + §4.3 consistently with §2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3077 high-level BLOCKING — Practice 4 classifications for PB-4 coproducts

Codex high-level BLOCKING (sha b812db91): "Diagnostic substrate
shape was repaired around anchoring but not re-audited as new
substrate type declarations" — meaning DiagnosticAnchor +
LowerDiagnostic + SurfaceFormRef + IdentifierRef need
🟢/🟡/🔴 classifications per modeling-discipline Practice 4
(Coproduct dissolution).

Same pattern as PB-5 fix in commit 040681f21 (AlgebraAxis +
InferDiagnostic) applied here.

Fix: added classifications + dissolution triggers:

- SurfaceFormRef 🟢 TERMINAL: closed-axis sum over live Surface*
  carriers; no further dissolution.
- IdentifierRef 🟡 SCAFFOLD: dissolution trigger = Step 2 brief
  enumerates full identifier-kind set against lower.rs
  identifier-resolution sites; promote to 🟢 TERMINAL when
  SurfaceVarRef + TypePathRef + ModulePathRef cover actual axes.
- LowerDiagnostic 🟡 SCAFFOLD: dissolution trigger = Step 2 brief
  enumerates variant set against lower.rs Diagnostic emission
  sites + Q6.5 anti-bridge preserved + PR #3077 §12 Q7
  ratification path.
- DiagnosticAnchor 🟢 TERMINAL: closed-axis covering all
  lowering-stage anchor kinds; no further dissolution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3077 INLINE BLOCKING line:161 — DiagnosticSource Practice 4 classification

Cursor inline finding adds DiagnosticSource to Practice 4
classification scope. Earlier commit aba79a142 classified
SurfaceFormRef + IdentifierRef + LowerDiagnostic + DiagnosticAnchor
but missed DiagnosticSource.

Fix: DiagnosticSource 🟢 TERMINAL at pipeline-stage
discrimination scope. Closed-axis sum (Parse | Lower | Infer |
Emit); adding new pipeline stage requires explicit substrate-
extension audit per Practice 4 + stop-signal discipline (same
shape as PB-5 §3.2 TypeConnective stop-signal).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 INLINE BLOCKING line:151 — §11 SurfaceItem::Let + SurfaceLiteral span correction

Cursor INLINE BLOCKING line:151: §11 claimed "every Surface
variant carries SourceSpan" but live parse_surface.dag has:
- SurfaceItem::Let { name, type_ann, expr } — no direct span
- SurfaceLiteral = Int(String) | Bool(Bool) | String(String) —
  plain-tuple variants with no direct span

Source-span provenance for these cases is via enclosing carrier:
SurfaceLiteral wraps within `Literal { value, span }` at
parse_surface.dag:150. Let-item inherits container span.

INVARIANTS P2/P3 source provenance is structurally guaranteed
via direct-OR-enclosing carrier, but my "every variant"
overstatement obscured this.

Fix: §11 corrected to "most Surface variants carry SourceSpan
directly" + explicit Let + SurfaceLiteral exceptions noted +
Step 2 PR scope audits whether exceptions are structural-honest
(enclosing-carrier-provides-span) OR require substrate extension.

Same recurring overstatement class as earlier "every SurfaceItem
maps 1:1 to Declaration" (commit 61e2b67cd) — need to grep live
substrate variant fields BEFORE claiming uniform shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: gunbc Director

* docs(r3): cursor PR #3126 INLINE BLOCKING line:32 — GrammarSpec is concept, not carrier

Earlier draft (now-merged PR #3126) framed `GrammarSpec` as a second declared
`.dag` input type alongside `List<Token>`. Verified via grep that no
`type GrammarSpec` exists anywhere under src/v3/ or dsl/ — the repo carries
only `parse_tables.dag`'s 6 SG-2c table-families. Per cursor 2026-05-14T23:30:04Z
inline finding, this violates INVARIANTS P2 (the Step-2 signature names a
carrier the substrate doesn't declare).

Reframed §3 (and downstream mentions in §3.2, §3 preamble line:33, §4.2
codex-correction recap line:165, §5.1 line:181, §12 Q6 line:344) so that:

- Parse has ONE input at the API boundary: `List<Token>`.
- "GrammarSpec" is a concept-level grouping for the 6 compile-time table-families
  in `parse_tables.dag`, not a substrate carrier and not a runtime parameter.
- Step-2 signature stays `fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>`
  per cfe842b2d (already applied in #3126); these edits remove the lingering
  "two input types" framing that contradicted that signature.

Per Decision 3.B (b) compile-time parser tables: substrate authority is
parse_tables.dag (6 table-families) consumed via direct table lookups inside
the parser body — no runtime grammar value, no `GrammarSpec` carrier needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3138 BLOCKING — §4.3 + §16 internal contradictions resolved

Codex review id 12391 on sha cd6e8d15 flagged two live statements of the
already-rejected typed-state-with-coupled-diagnostics model still sitting
inside the parse L2.5, contradicting the corrected Result-sum framing in §4.2
and §6 Step 2:

1. §4.3 still proposed a `SurfaceModule { items, diagnostics }` extension
   modeled on PB-4/PB-5 patterns. Reframed: §4.3 now states explicitly that
   parse-stage uses Result-sum (no diagnostics field on SurfaceModule),
   restates the cross-stage discriminator (Result-sum for fail-fast output
   domains: parse + emit; typed-state for structural output domains: lower +
   infer), and cites `parse_generated.rs:138` as the live shape.

2. §16 "Memory disciplines applied" bullet read
   "feedback_state_space_vs_behavioral_invariants (typed-state SurfaceModule
   at output)". Rewritten to "parse output is `Result<SurfaceModule,
   ParseDiagnostic>` — the type rules out partial-parse states by
   construction; SurfaceModule itself carries no diagnostic field per §4.3".

Per `feedback_discipline_change_audit_all_contract_mentions`: when a
contract changes (here: SurfaceModule extension dropped in favor of
Result-sum), all §-internal restatements must be swept in the same diff
or they leak through as authoritative parallel claims.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3127 BLOCKING — drop TokenizedSource extension + cite concrete P5 receipts

Codex review id 12370 on sha d15e1f29 raised two load-bearing planning-shape
findings on the tokenize L2.5. Addressed in this fix-forward branch (PR #3138)
since PR #3127 is still open but accumulating cycles.

Finding 1 — parallel boundary carriers (INVARIANTS P2 / Modeling Practices 3+5):
§4.3 + §9 Step 2 + §12 Q6 named `TokenizedSource { tokens, diagnostics }` as the
output, while §2/§7.2/§7.3 named `List<Token>`. Same misclassification I just
removed from the parse L2.5 in PR #3138 §4.3: tokenize sits in the fail-fast
output domain alongside PB-3 parse + PB-6 emit (a partial token list with a
corrupt token in the middle is not a valid downstream input for parse), so the
failure couples via `Result`, not into the structural carrier.

Resolution:
- §4.3 rewritten to ratify `Result<List<Token>, TokenizeDiagnostic>` — the live
  `tokenize_generated.rs:96` shape — with no `TokenizedSource` extension.
- §9 Step 2 row signature updated to match; explicit "single canonical boundary
  carrier: List<Token> on the Ok branch" framing.
- §12 Q6 resolved REJECTED in-doc (no operator ratification needed; disposition
  follows from the cross-stage discriminator that's also load-bearing in PR
  #3138 parse L2.5).
- §16 memory-disciplines bullets rewritten parallel to PR #3138 parse §16:
  Result-sum, no diagnostics field on `List<Token>`.
- §14 "Surfaces awaiting" trimmed Q6 from the operator-ratification list.

Finding 2 — soft deferral of `regen_tokenize` retirement (INVARIANTS P5):
deferral previously named "PB-Bootstrap-Process lane scope" without a concrete
ROADMAP.md row. Updated §9 Step 2 + Step 4 rows to cite the named receipts:
- `docs/design-pure-bootstrap-zero.md:116` (PB-Bootstrap-Process lane: author
  bootstrap.dag + generated trampoline; sized M).
- `docs/design-pure-bootstrap-zero.md:118-123` (N=0 runtime verification gates).
- ROADMAP.md:467 (Character-level under-consumption in tokenize + syntax
  authorities — phase-2 char-class retype owns the codegen-driver path).
- ROADMAP.md:416 (Class 5 Gap 3 — top-level `ValueBody` boundary; gating
  substrate-capability for the phase-2 retype).
- ROADMAP.md:53 (T-PB-A — non-test census → 0 floor).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3126 BLOCKING line:119 — §6/§7.2/§15 Q7 sequencing resolved by PR #3077 merge

Cursor inline BLOCKING at docs/design-parse-stage-l25-model.md:119 (sha at
merge time of PR #3126) flagged a real internal contradiction:
- §6 (lines 191, 207, 308) claimed "Step 2 (pipeline-slot declaration) is
  unblocked"
- §7.2 (line 227) claimed "PR #3077 §12 Q7 must ratify before any Step 2
  worker brief authoring"

A worker reading the doc could land Step 2 (pipeline boundary) before the
diagnostic carrier's P2/P3 failure shape was fixed.

Resolution: PR #3077 (PB-4 lower L2.5) merged at 2026-05-15T00:21:19Z,
carrying the §12 Q7 ratification of the Decision 2.B per-stage diagnostic
extension path. The gate IS now satisfied at HEAD, so the resolution is
fact-update (annotate Q7 as DONE with the merge timestamp) rather than
retracting either §6 or §7.2.

Edits:
- §15 step 4: annotated "DONE 2026-05-15T00:21:19Z when PR #3077 merged"
  and added the explicit "Step 2 is now genuinely unblocked, not just
  procedurally next" framing so workers reading the sequence don't bypass
  the gate.
- §7.2 line 227: rewritten from "Q7 must ratify before Step 2 brief
  authoring" (future tense, the contradiction surface) to "Gate satisfied
  2026-05-15T00:21:19Z when PR #3077 merged; Step 2 worker brief authoring
  is unblocked at HEAD per §15 step 4." Cites the cursor finding as the
  resolution path.

§6 unblocking statements stay as-is — they were correct at HEAD; the
contradiction lived in §7.2's pre-merge framing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3126 BLOCKING (sha 16d21f4a) — Q7 cited at every Step 2 unblocking claim

Codex BLOCKING finding 2 (sha 16d21f4a, 216s thinking): the Q7 dependency
was recorded in §7.2/§15 but not in the other Step-2-unblocking sites at
§6 lines 191, 207, 308 — risking a worker reading "Step 2 unblocked" without
also reading the Q7 prerequisite.

Codex framing: "make Q7 a hard precondition wherever Step 2 is called
unblocked, or split Step 2 into pre-Q7 and post-Q7 scopes with separate
receipts."

Chose the first option since PR #3077 has already merged (2026-05-15T00:21:19Z)
and splitting into pre/post-Q7 scopes is no longer load-bearing. Annotated
all three §6 sites:
- Line 191 (Implication for PB-3 migration): cites gate + merge timestamp
  + explicit "must NOT be brief-authored before that merge timestamp."
- Line 207 (Critical observation): cites the Step 2 gate as PR #3077 §12 Q7
  + merge timestamp + P3 failure-shape consequence if violated.
- Line 308 (Director-recommend phase list): cites gate + §7.2/§15 step 4
  cross-refs + merge timestamp.

Codex BLOCKING finding 1 (GrammarSpec carrier non-existence) verified
already resolved at HEAD via commit c97dc15ae — every GrammarSpec mention
now explicitly marks it as a concept-not-carrier; Step 2 signature is
`fn parse(tokens: List<Token>) -> Result<SurfaceModule, ParseDiagnostic>`
with no GrammarSpec parameter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): openai-pro PR #3126 BLOCKING (sha 16d21f4a) — Step 3b/4 atomicity + Q1 ratification-pending status

openai-pro REQUEST_CHANGES on PR #3126 sha 16d21f4a flagged three findings.
Findings 1 + 2 (signature vs realization mismatch under LAYER MODEL + P2/P3
boundary discipline) were already resolved at HEAD by earlier fix-forward
commits — Step 2 signature is now `fn parse(tokens: List<Token>) ->
Result<SurfaceModule, ParseDiagnostic>` matching live `parse_generated.rs:138`
with no GrammarSpec parameter and no diagnostics-coupled SurfaceModule
extension (§4.3 Result-sum disposition).

Finding 6 (TRACKED vs UNTRACKED DEBT — Step 3b/4 same-PR vs two-PR):
§9 had both a "Step 3b/4 COMBINED" row (line 250) and a leftover separate
"Step 4: Parity test" row (line 251) — internally contradictory. §15 also
still sequenced Steps 3b + 4 as four separate authoring/dispatch/ratify
beats (steps 12-17), contradicting §12 Q5's "same PR" decision and the
explicit "Update to §15" note at §12 line 325.

Resolution: collapsed §9 to one COMBINED row absorbing the parity-TestClaim
mechanics + P5 dissolution receipt from the deleted Step 4 row; collapsed
§15 steps 12-17 into single COMBINED authoring + dispatch + ratify (steps
12-14). Added explicit `feedback_paper_shrink_variants` reasoning in both
sections.

Finding 2.5 (PM intent — substrate-capability bundled vs separate):
§12 Q1 line 288 said "Director-recommend: (b) bundled" while §13 line 340
listed substrate-capability as a non-goal of PB-3 and §15 step 11 had
"WAIT for substrate-capability landing" — three sections, two different
execution paths.

Resolution: annotated Q1 as "PENDING operator/PM ratification" with
explicit default-execution clause: until operator ratifies, the doc
treats substrate-capability as path (a) separate lane (matching §13 + §15
+ §9 row). If/when ratified to (b), §13 drops the non-goal and §15 step 11
collapses into the COMBINED Step 3b/4 brief.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3126 BLOCKING (sha 5619afac) — parse_tables.dag as single enumerated authority

Codex caught me copying the prose summary at parse_tables.dag:23-29 (which
enumerates only SG-2c-numbered families) instead of grepping the live
`^type [A-Z]` declarations. Result: SoftKeywordIdentRow (line 334) was
missing from §3.2 / §5.1 / §6 / §12 because it lacks an SG-2c-N number
in the prose summary.

Per `feedback_parallel_representation_debt`: structural fix is to stop
hand-enumerating in the doc — cite parse_tables.dag itself as the single
enumerated authority and use `type`-declaration line-anchors for the
worked example, not a hand-maintained count.

Edits:
- §3.2 §"Live substrate authority": replaced the SG-2c-numbered bullet
  list with `type`-declaration line-anchor enumeration including
  SoftKeywordIdentRow at parse_tables.dag:334 + the supporting enum
  BinaryOpLevel at line 133. Added codex-finding callout explaining the
  miss + the discipline shift.
- §3 preamble line:33, §3.2 line:45 callout, §3.2 line:57 framing,
  §3.2 §"Substrate authority" line:71, §5.1 line:171-180, §12 Q2 line:298,
  §12 Q6 line:334: all hardcoded "6 table-families" counts dropped; doc
  now points readers to §3.2 enumeration / `parse_tables.dag` directly.
- §5.1 sub-enumeration list (the parallel 6-item list at lines 173-178)
  deleted; replaced with redirect to §3.2 + restated 3a-vs-3b/4 scope split.

Code-level check before commit: `grep -nE '^type [A-Z]' src/v3/compiler/parse_tables.dag`
returns 7 types: BinaryOpLevel (133), BinaryOpRow (167), TopLevelItemKwRow (289),
SoftKeywordIdentRow (334), BracketRow (385), PrimaryPrefixRow (449),
PrimaryAtomRow (486). Doc enumeration matches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3138 BLOCKING (sha f08b9525) — bind TokenizeDiagnostic to live CharClass authority

Codex Finding 1 (sha f08b9525, 216s thinking): the §4.2 TokenizeDiagnostic
draft and the §5.1/§5.2 headings used `ScannerCharClass` / `ScannerClassRef`
— names that exist only as the *generated Rust enum spelling*, not as a
declared .dag substrate type. Verified via grep:

  grep -rn '^type CharClass\|^type ScannerC' dsl/ src/v3/

returns ONE authority: `dsl/std/unicode.dag:62`
  type CharClass = Whitespace | Digit | IdentStart | IdentContinue

consumed at `src/v3/compiler/tokenize.dag:103`
  data ascii_scan_order: List<CharClass> = [Whitespace, Digit, IdentStart, IdentContinue]

There is no `ScannerCharClass` declaration anywhere — that name was copied
from generated Rust without grep-verification, the same failure mode as
`feedback_grep_substrate_before_naming_ratification` (carrier-name
collision discipline).

Resolution:
- §4.2 TokenizeDiagnostic carrier: `expected_class: ScannerClassRef` →
  `expected_class: CharClass`, dropped the `type ScannerClassRef =
  ScannerCharClass` alias entirely; added a codex-finding callout citing
  the substrate authority + naming the failure mode.
- §5.1 heading "Byte → ScannerCharClass dispatch" → "Byte → CharClass
  dispatch"; bullets unchanged; added line-anchor cites for the substrate
  authority + explicit "NOT ScannerCharClass" disclaimer.
- §5.2 heading "ScannerCharClass → token-recognition state machine" →
  "CharClass → token-recognition state machine".

Finding 2 (TokenizedSource not reconciled with parse input contract): no
new fix required — already resolved by commit 6adb99227 (TokenizedSource
extension dropped entirely; tokenize uses Result<List<Token>,
TokenizeDiagnostic>; List<Token> is the single canonical boundary carrier
consumed by parse). Codex was reviewing sha f08b9525, which predated the
TokenizedSource drop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3138 INLINE BLOCKING line:188 — clarify §7.3 chain is Ok-branch propagation

Cursor INLINE at sha f08b9525 worried that §7.3's cross-stage chain
"tokenize → List<Token> → parse → ..." was inconsistent with §4.3's
TokenizedSource carrier (diagnostics not flowing forward). At HEAD the
TokenizedSource extension is dropped (commit 6adb99227); tokenize uses
Result<List<Token>, TokenizeDiagnostic>, so List<Token> IS the canonical
Ok-branch payload that flows forward and Err branches terminate the
pipeline fail-fast.

To make this explicit at §7.3 (instead of leaving readers to infer it
from §4.3), annotated the chain with:
- "Ok-branch propagation; Err branches are stage-terminal fail-fast per
  §4.3 Result-sum discriminator" framing prefix.
- Per-stage Result/typed-state annotations: tokenize/parse show
  Result<Ok, Err>; lower/infer show typed-state structural-output;
  emit shows Result<EmittedArtifact, EmissionDiagnostic>.
- Explicit "on any stage's Err branch the pipeline aborts at that stage
  (no partial-output propagation across boundaries)" trailer.

This makes the chain self-consistent vis-a-vis §4.3 without requiring
the reader to walk back-and-forth, and prevents future readers from
re-introducing a TokenizedSource-shaped extension to "make diagnostics
flow forward" — they already do, just via the Err branch terminating
the pipeline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): openai-pro PR #3127 BLOCKING (sha d15e1f29) — character-level scaffold dissolution trigger

openai-pro REQUEST_CHANGES on sha d15e1f29: §1 line:26 character-level
under-consumption scaffold named the problem but lacked a checkable
dissolution trigger. SG-1a scaffold above had the right shape — "once
those bodies lower structurally under compile_to_dag, delete the raw-text
extractor + derive directly from lowered Dag in same PR." Character-level
scaffold just said "PB-2 Step 4 carries this scope" — a lane assignment,
not a trigger.

Resolution: rewrote §1 item 2 with the same SG-1a-shape trigger structure:
- Substrate-consumption condition (a): scanner classes / string escape /
  local punctuation retype to `dsl/std/unicode.dag` `CharClass` /
  `char_in_class` (concrete field retypes named:
  `StringEscapeSpec.suffix: Char`, `LocalPunctSpec.pattern: List<Char>`,
  `string_literal_delimiter: Char`).
- Codegen-driver condition (b): `tokenize_generated.rs` no longer emits
  hidden `byte.is_ascii_*` predicates because the driver reads class
  facts structurally from lowered `tokenize.dag`.
- Same-PR dissolution: delete the parallel character-predicate scaffold
  in the same PR that flips substrate consumption — no Rust-and-`.dag`
  coexistence per `feedback_paper_shrink_variants`.
- Cross-ref to §9 Step 4 gating prereqs: ROADMAP.md:467 + ROADMAP.md:416
  Class 5 Gap 3 + std.unicode bootstrap/load-set decision (already cited
  in §9 from earlier commit 6adb99227).

Per openai-pro's framing: "small fix — mirror the SG-1a scaffold wording
by naming the exact substrate-consumption condition and same-PR deletion
receipt for the hidden Rust character predicates."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* WIP: gunbc Director

* docs(r3): cursor PR #3127 APPROVE_WITH_COMMENTS — §14 + §15 Q6-already-rejected sweep

Cursor review id 12405 (APPROVE_WITH_COMMENTS) caught the same
`feedback_discipline_change_audit_all_contract_mentions` failure mode
recurring: §12 Q6 was resolved REJECTED in commit 6adb99227, and §14
"Surfaces awaiting" + §12 Q6 heading + §9 Step 2 row were updated, but
two §-internal contract restatements were missed:

- §14 acceptance criterion 11: "Operator/PM ratification on §12 Q1-Q6"
- §15 step 1: "Operator / PM-delegate ratifies §12 Q1-Q6"

Both contradicted §12 Q6 + §14 "Surfaces awaiting" (which already said
"Q1-Q5 only"). A worker reading §14/§15 could schedule sign-offs on Q6
after it was already resolved-rejected elsewhere.

Resolution: both sites now say "Q1–Q5" with the explicit Q6-rejected
crossref + "see §14/§15 for same scoping" pointer at the §14 criterion
so the three sections agree internally.

Cursor verdict was APPROVE_WITH_COMMENTS (substantive APPROVE — "fix the
checklist/sequence so every section agrees Q6 is closed"); the
exploratory volatile-line-anchor note is harmless and out-of-scope for
this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3138 BLOCKING (sha 887c69671) — 3 findings swept across 3 L2.5 docs

Codex review id (sha 887c69671, 333s thinking) flagged three findings,
all `feedback_discipline_change_audit_all_contract_mentions` recurrences
where partial sweeps left §-internal contradictions.

Finding 1 — infer doc cross-stage trigger leak:
§4.2 InferDiagnostic dissolution trigger said "when Step 2 worker brief
enumerates the full variant set against `parse_generated.rs`
Diagnostic::ParseError, lower.rs Diagnostic construction sites, and
infer.rs Dag::mark_unresolved emission sites." That cross-stage trigger
surface is wrong for the infer-specific scaffold. Narrowed to infer-only:
"against `src/v3/compiler/src/infer.rs` Diagnostic construction sites +
`Dag::mark_unresolved` emission sites (infer-stage only)." Parse and lower
have their own per-stage carriers + own Q7 mapping; this doc no longer
reaches into their dissolution-trigger surface.

Finding 2 — parse + tokenize coproduct receipts:
`ParseDiagnosticKind` (parse §4.2) and `TokenizeDiagnostic` (tokenize §4.2)
sums were declared without the 🟡 SCAFFOLD / 🟢 TERMINAL classification +
dissolution trigger that the infer doc carries (per modeling-discipline
Practice 4 + `feedback_coproduct_dissolution`). Added matching scaffold
receipts to both: 🟡 SCAFFOLD at PROPOSED stage with stage-local dissolution
trigger (Step 2 brief enumerates against parse_generated.rs / tokenize_generated.rs
Diagnostic::* construction sites — stage-only, not cross-stage); promote
to 🟢 TERMINAL when full variant set lands. Both also carry the anti-bridge
note per Q6.5.

Finding 3 — tokenize Q7 reconciliation:
The parse doc has the "Q7 DONE 2026-05-15T00:21:19Z" annotation at §15 step 4
(commit f85fa1f6b) but the tokenize doc still framed Q7 as a pending lane
dependency at §4.2 line:113 ("Lane dependency"), §15 step 3, and §14
"Surfaces awaiting". Annotated all three:
- §4.2 "Lane dependency": Q7 DONE timestamp + "TokenizeDiagnostic per-stage
  variant authoring is the remaining lane work."
- §15 step 3: full DONE annotation matching parse doc §15 step 4 shape +
  cross-ref to the parse doc.
- §14 "Surfaces awaiting": strikethrough + DONE annotation.

PR #3127 also carries the tokenize doc; same edits will port there in a
companion commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3138 INLINE BLOCKING line:372 — §16 Surfaces awaiting Q7 contradiction

Cursor inline at sha 887c69671 caught the symmetric finding to the codex
5-finding BLOCKING #3: parse-doc §15 step 4 already annotated Q7 as DONE
(commit f85fa1f6b) but parse-doc §16 "Surfaces awaiting" still listed Q7
as pending. Same `feedback_discipline_change_audit_all_contract_mentions`
sweep failure — the tokenize doc had three sites carrying the pending
framing (commit e9739ea4f fixed those) but the parse doc's §16 site was
missed in the original Q7-DONE sweep.

Resolution: §16 bullet now strikes through + "DONE 2026-05-15T00:21:19Z
(PR #3077 merged carrying Q7 ratification; see §15 step 4)" — same shape
as the tokenize doc's §14 "Surfaces awaiting" Q7-DONE annotation landed
in e9739ea4f.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): codex PR #3127 BLOCKING (sha 8e682eef) — §3.1 source identity + §4.2 live-vs-proposed clarity

PR #3127 was merged at 02:04:22Z but codex's later review on sha 8e682eef
caught two findings that still live in main. Both addressed in this PR
(PR #3140) since the tokenize doc lives on main and this is the open
post-merge cleanup branch.

Finding 1 — §3.1 source-identity drop:
Earlier draft framed tokenize input as bare `String → List<Token>`. That
contradicts live `tokenize_generated.rs:96`:
  pub fn tokenize(source: &str, file: &str) -> Result<Vec<Token>, Diagnostic>
The `file` parameter is load-bearing because `SourceSpan` requires a
file/source-id field for byte ranges to be attributable; without it the
Token + Diagnostic span fields would have to fabricate source-id at the
pipeline boundary (P3 fail-closed violation). §3.1 now ratifies the live
two-input shape:
- `source: String` — UTF-8 source text (primitive).
- `file: SourceFileId` — source-identity carrier; Step 2 brief ratifies
  the appropriate `.dag` shape (NonEmptyStr newtype or richer sum if
  multiple source-class kinds).

Finding 2 — §4.2 live-vs-proposed blur:
Prior framing said "TokenizeDiagnostic (substrate extension per Decision
2.B)" without making clear that this is a PROPOSED per-stage carrier,
not the live one. The live carrier at `diagnostics.dag:150` is generic
`Diagnostic { kind: AnyDiagnosticKind, ... }` with kind sum at `:139-142`
discriminating CompilerKind vs LensInstanceKind; tokenize emits today
via `Diagnostic::TokenizerError`-shaped sites carrying
`kind: CompilerKind(...)`. §4.2 heading now reads "PROPOSED — NOT yet
live" + a codex-finding callout explicitly distinguishing the live
carrier from the proposed per-stage refinement + Q7 status DONE.

Both fixes preserve the e9739ea4f 🟡 SCAFFOLD coproduct receipt that
was already addressing codex sha 887c69671 Finding 2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3127 INLINE BLOCKING line:121 — §4.3 + §9 Step 2 signature sweep

Cursor inline at sha 8e682eef line:121 (the §4.3 Step 2 signature site)
caught the same source-identity drop my §3.1 fix already addressed at the
input-type framing — but two companion sites still had the single-input
signature:
- §4.3 line:151 Step 2 signature recap
- §9 Step 2 row (4-step migration table)

Both now read:
  fn tokenize(source: String, file: SourceFileId) -> Result<List<Token>, TokenizeDiagnostic>

matching the §3.1 source-identity discipline + live `tokenize_generated.rs:96`
`pub fn tokenize(source: &str, file: &str)` shape.

Same `feedback_discipline_change_audit_all_contract_mentions` recurrence
— my Finding 1 fix at §3.1 (commit 18af49fad) didn't sweep the §4.3 + §9
contract-signature restatements.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3127 INLINE BLOCKING line:166 — §6 row TokenizeDiagnostic LIVE/PROPOSED clarity

Cursor inline caught ambiguity in the §6 prereq-table row for
"TokenizeDiagnostic substrate extension." Old wording in column 4 read
"Carrier LIVE; per-stage variant authoring NEW" which could be parsed
as "TokenizeDiagnostic carrier itself is LIVE" — but no `type
TokenizeDiagnostic` exists in `dsl/std/` or `src/v3/std/`. Only the
generic `type Diagnostic` at `diagnostics.dag:150` is live.

Cursor's secondary claim that "line 150 is EmissionDiagnostic receipt
prose" is INCORRECT — verified via grep + read: `diagnostics.dag:150`
is the `type Diagnostic { kind: AnyDiagnosticKind, ... }` declaration
header. `type EmissionDiagnostic` lives separately at `diagnostics.dag:201`.
The §6 row's citation of `:150` for the underlying Diagnostic carrier
is correct.

But the ambiguity-in-wording finding stands. Reframed the row:
- Column 1: explicitly "PROPOSED — no `type TokenizeDiagnostic` exists yet"
- Column 2: clarifies the LIVE underlying carrier is `type Diagnostic`
  with `kind: AnyDiagnosticKind` sum at `:139-142`; cites Q7 ratification
  done timestamp.
- Column 4: explicit "Underlying Diagnostic carrier LIVE at HEAD;
  per-stage TokenizeDiagnostic variant authoring is NEW work, NOT live
  substrate" with cursor-finding callout.

Consistent with §4.2's "PROPOSED — NOT yet live" framing from commit
18af49fad.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3141 INLINE BLOCKING line:68 — §2 structural-signature sweep

Cursor inline caught §2 still framing tokenize structural signature as
`String → List<Token>` — single bare-string input, no source-identity,
no Result-sum failure shape — while §3.1 + §4.3 + §9 Step 2 row all
ratify the live two-input + fail-fast Result-sum shape.

Same `feedback_discipline_change_audit_all_contract_mentions` recurrence
that's been compounding across this fix-forward sequence: each finding
fix needs a doc-wide signature-restatement sweep, not just the §-local
sentence.

Resolution: §2 structural-shape sentence now reads
  `(String, SourceFileId) → Result<List<Token>, TokenizeDiagnostic>`
matching §3.1 (source-identity), §4.3 (Result-sum cross-stage
discriminator), §9 Step 2 row, and live `tokenize_generated.rs:96`
`pub fn tokenize(source: &str, file: &str) -> Result<Vec<Token>,
Diagnostic>`. Cross-refs added to §3.1 + §4.3 to make the discipline
visible at the high-level framing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(r3): cursor PR #3141 INLINE BLOCKING line:73 — replace invented SourceFileId with live FilePath

Cursor caught me inventing `SourceFileId` as the Step 2 boundary type
without a live `.dag` declaration. Verified via grep:
  grep -rn '^type SourceFileId' dsl/ src/v3/
returns empty. Same `feedback_grep_substrate_before_naming_ratification`
family error as the earlier `ScannerCharClass` miss — naming a substrate
carrier without grep-verification.

Live carrier already exists at `dsl/std/types.dag:276`:
  type FilePath = String where non_empty

referenced by `type SourceSpan { file: FilePath, ... }` at
`dsl/std/types.dag:293`. So source identity flows through every Token +
Diagnostic span field via the live `FilePath` carrier — no new carrier
authoring needed at Step 2.

Edits:
- §2 structural-signature: `(String, SourceFileId)` → `(String, FilePath)`
- §3.1 source-identity bullet: replaces fictional SourceFileId with the
  live `FilePath` declaration cite (dsl/std/types.dag:276), points out
  that `SourceSpan.file` already references this same carrier, and adds
  a cursor-finding callout naming the failure mode.
- §4.3 + §9 Step 2 signature restatements: `file: SourceFileId` →
  `file: FilePath`.

Single substrate authority (INVARIANTS P1/P2) restored: FilePath is the
one carrier for source identity across SourceSpan + tokenize input +
Token construction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant